DATACASS-310 - Fix CqlTemplate and CassandraTemplate returning null for data access operations returning a Collection.

This commit is contained in:
John Blum
2016-07-01 17:26:04 -07:00
parent 931e777498
commit ab73021187
8 changed files with 755 additions and 156 deletions

View File

@@ -124,6 +124,34 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
return cql;
}
protected <T extends Statement> T logStatement(T statement) {
logDebug("executing statement [{}]", statement);
return statement;
}
/**
* Add common {@link QueryOptions} to Cassandra {@link PreparedStatement}s.
*
* @param preparedStatement the Cassandra {@link PreparedStatement} to execute.
* @param queryOptions query options (e.g. consistency level) to add to the Cassandra {@link PreparedStatement}.
*/
public static PreparedStatement addPreparedStatementOptions(PreparedStatement preparedStatement,
QueryOptions queryOptions) {
if (queryOptions != null) {
if (queryOptions.getConsistencyLevel() != null) {
preparedStatement.setConsistencyLevel(ConsistencyLevelResolver.resolve(queryOptions.getConsistencyLevel()));
}
if (queryOptions.getRetryPolicy() != null) {
preparedStatement.setRetryPolicy(RetryPolicyResolver.resolve(queryOptions.getRetryPolicy()));
}
}
return preparedStatement;
}
/**
* Add common {@link QueryOptions} to all types of queries.
*
@@ -189,29 +217,6 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
return update;
}
/**
* Add common {@link QueryOptions} to Cassandra {@link PreparedStatement}s.
*
* @param preparedStatement the Cassandra {@link PreparedStatement} to execute.
* @param queryOptions query options (e.g. consistency level) to add to the Cassandra {@link PreparedStatement}.
*/
public static PreparedStatement addPreparedStatementOptions(PreparedStatement preparedStatement,
QueryOptions queryOptions) {
if (queryOptions != null) {
if (queryOptions.getConsistencyLevel() != null) {
preparedStatement.setConsistencyLevel(ConsistencyLevelResolver.resolve(queryOptions.getConsistencyLevel()));
}
if (queryOptions.getRetryPolicy() != null) {
preparedStatement.setRetryPolicy(RetryPolicyResolver.resolve(queryOptions.getRetryPolicy()));
}
}
return preparedStatement;
}
/**
* Constructs an uninitialized instance of {@link CqlTemplate}. A Cassandra {@link Session} is required before use.
*
@@ -227,7 +232,7 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
* @see com.datastax.driver.core.Session
* @see #setSession(Session)
*/
// TODO should probably not call setSession(..) in constructor for initialization safety;
// TODO: should not call setSession(..) in constructor for initialization safety;
// only really matters if CqlTemplate makes Thread-safety guarantees, which currently it does not.
public CqlTemplate(Session session) {
setSession(session);
@@ -242,15 +247,32 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
*/
protected <T> T doExecute(SessionCallback<T> callback) {
Assert.notNull(callback);
Assert.notNull(callback, "SessionCallback must not be null");
try {
return callback.doInSession(getSession());
} catch (DataAccessException e) {
} catch (Exception e) {
throw translateExceptionIfPossible(e);
}
}
protected ResultSet doExecuteQueryReturnResultSet(final String query) {
return doExecute(new SessionCallback<ResultSet>() {
@Override
public ResultSet doInSession(Session session) throws DataAccessException {
return session.execute(logCql(query));
}
});
}
protected ResultSet doExecuteQueryReturnResultSet(final Select select) {
return doExecute(new SessionCallback<ResultSet>() {
@Override public ResultSet doInSession(Session session) throws DataAccessException {
return session.execute(logStatement(select));
}
});
}
@Override
public <T> T execute(SessionCallback<T> sessionCallback) {
return doExecute(sessionCallback);
@@ -960,6 +982,7 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
@Override
public <T> T query(String cql, PreparedStatementBinder preparedStatementBinder,
ResultSetExtractor<T> resultSetExtractor) {
return query(cql, preparedStatementBinder, resultSetExtractor, null);
}
@@ -974,6 +997,7 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
@Override
public void query(String cql, PreparedStatementBinder preparedStatementBinder,
RowCallbackHandler rowCallbackHandler) {
query(cql, preparedStatementBinder, rowCallbackHandler, null);
}
@@ -992,13 +1016,15 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
@Override
public <T> List<T> query(String cql, PreparedStatementBinder preparedStatementBinder, RowMapper<T> rowMapper,
QueryOptions queryOptions) {
return query(new CachedPreparedStatementCreator(logCql(cql)), preparedStatementBinder, rowMapper, queryOptions);
}
@Override
public void ingest(String cql, RowIterator rowIterator, WriteOptions options) {
CachedPreparedStatementCreator cachedPreparedStatementCreator = new CachedPreparedStatementCreator(logCql(cql));
CachedPreparedStatementCreator cachedPreparedStatementCreator =
new CachedPreparedStatementCreator(logCql(cql));
PreparedStatement preparedStatement = addPreparedStatementOptions(
cachedPreparedStatementCreator.createPreparedStatement(getSession()), options);
@@ -1023,8 +1049,8 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
@Override
public void ingest(String cql, final List<List<?>> rows, WriteOptions writeOptions) {
Assert.notNull(rows);
Assert.notEmpty(rows);
Assert.notNull(rows, "Rows must not be null");
Assert.notEmpty(rows, "Rows must not be empty");
ingest(cql, new RowIterator() {
@@ -1056,17 +1082,17 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
int index = 0;
@Override
public Object[] next() {
if (!hasNext()) {
throw new NoSuchElementException("No more elements");
}
return rows[index++];
public boolean hasNext() {
return (index < rows.length);
}
@Override
public boolean hasNext() {
return (index < rows.length);
public Object[] next() {
if (!hasNext()) {
throw new NoSuchElementException("No more elements");
}
return rows[index++];
}
}, writeOptions);
}
@@ -1160,6 +1186,7 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
@Override
public <T> List<T> query(PreparedStatementCreator preparedStatementCreator,
PreparedStatementBinder preparedStatementBinder, RowMapper<T> rowMapper) {
return query(preparedStatementCreator, preparedStatementBinder, rowMapper, null);
}
@@ -1350,19 +1377,16 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
@Override
public Cancellable executeAsynchronously(Insert insert, AsynchronousQueryListener listener) {
return doExecuteAsync(insert, listener);
}
@Override
public Cancellable executeAsynchronously(Truncate truncate, AsynchronousQueryListener listener) {
return doExecuteAsync(truncate, listener);
}
@Override
public Cancellable executeAsynchronously(Update update, AsynchronousQueryListener listener) {
return doExecuteAsync(update, listener);
}
@@ -1572,7 +1596,6 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
@Override
public Cancellable queryForMapAsynchronously(String cql, QueryForMapListener listener) {
return queryForMapAsynchronously(cql, listener, null);
}
@@ -1709,7 +1732,6 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
@Override
public ResultSet getResultSetUninterruptibly(ResultSetFuture resultSetFuture, long timeout, TimeUnit timeUnit) {
try {
timeUnit = (timeUnit != null ? timeUnit : TimeUnit.MILLISECONDS);

View File

@@ -0,0 +1,121 @@
/*
* Copyright 2013-2016 the original author or authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cassandra.core.support;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import com.datastax.driver.core.ExecutionInfo;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;
/**
* An empty {@link com.datastax.driver.core.ResultSet} implementation
*
* @author John Blum
* @see org.springframework.cassandra.core.support.ResultSetAdapter
* @see com.datastax.driver.core.ResultSet
* @since 1.5.0
*/
public class EmptyResultSet extends ResultSetAdapter {
protected static final EmptyResultSet INSTANCE = new EmptyResultSet();
/**
* Returns the given {@link ResultSet} if not null, otherwise returns an empty {@link ResultSet}.
*
* @param resultSet {@link ResultSet} to evaluate for {@literal null}.
* @return the given {@link ResultSet} if not null, otherwise return an empty {@link ResultSet}.
* @see com.datastax.driver.core.ResultSet
*/
public static ResultSet nullSafeResultSet(ResultSet resultSet) {
return (resultSet != null ? resultSet : EmptyResultSet.INSTANCE);
}
/*
* (non-Javadoc)
* @see com.datastax.driver.core.ResultSet#isExhausted()
*/
@Override
public boolean isExhausted() {
return true;
}
/*
* (non-Javadoc)
* @see com.datastax.driver.core.ResultSet#isFullyFetched()
*/
@Override
public boolean isFullyFetched() {
return true;
}
/*
* (non-Javadoc)
* @see com.datastax.driver.core.ResultSet#getAvailableWithoutFetching()
*/
@Override
public int getAvailableWithoutFetching() {
return 0;
}
/*
* (non-Javadoc)
* @see com.datastax.driver.core.ResultSet#getAllExecutionInfo()
*/
@Override
public List<ExecutionInfo> getAllExecutionInfo() {
return Collections.emptyList();
}
/*
* (non-Javadoc)
* @see com.datastax.driver.core.ResultSet#getExecutionInfo()
*/
@Override
public ExecutionInfo getExecutionInfo() {
return null;
}
/*
* (non-Javadoc)
* @see com.datastax.driver.core.ResultSet#all()
*/
@Override
public List<Row> all() {
return Collections.emptyList();
}
/*
* (non-Javadoc)
* @see com.datastax.driver.core.ResultSet#iterator()
*/
@Override
public Iterator<Row> iterator() {
return Collections.emptyIterator();
}
/*
* (non-Javadoc)
* @see com.datastax.driver.core.ResultSet#one()
*/
@Override
public Row one() {
return null;
}
}

View File

@@ -0,0 +1,137 @@
/*
* Copyright 2013-2016 the original author or authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cassandra.core.support;
import java.util.Iterator;
import java.util.List;
import com.datastax.driver.core.ColumnDefinitions;
import com.datastax.driver.core.ExecutionInfo;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;
import com.google.common.util.concurrent.ListenableFuture;
/**
* An Adapter class to simply implementations of the {@link ResultSet} interface.
*
* @author John Blum
* @see com.datastax.driver.core.ResultSet
* @since 1.5.0
*/
public class ResultSetAdapter implements ResultSet {
private static final String NOT_SUPPORTED = "Not Supported";
/*
* (non-Javadoc)
* @see com.datastax.driver.core.ResultSet#isExhausted()
*/
@Override
public boolean isExhausted() {
throw new UnsupportedOperationException(NOT_SUPPORTED);
}
/*
* (non-Javadoc)
* @see com.datastax.driver.core.ResultSet#isFullyFetched()
*/
@Override
public boolean isFullyFetched() {
throw new UnsupportedOperationException(NOT_SUPPORTED);
}
/*
* (non-Javadoc)
* @see com.datastax.driver.core.ResultSet#getAvailableWithoutFetching()
*/
@Override
public int getAvailableWithoutFetching() {
throw new UnsupportedOperationException(NOT_SUPPORTED);
}
/*
* (non-Javadoc)
* @see com.datastax.driver.core.ResultSet#getColumnDefinitions()
*/
@Override
public ColumnDefinitions getColumnDefinitions() {
throw new UnsupportedOperationException(NOT_SUPPORTED);
}
/*
* (non-Javadoc)
* @see com.datastax.driver.core.ResultSet#getAllExecutionInfo()
*/
@Override
public List<ExecutionInfo> getAllExecutionInfo() {
throw new UnsupportedOperationException(NOT_SUPPORTED);
}
/*
* (non-Javadoc)
* @see com.datastax.driver.core.ResultSet#getExecutionInfo()
*/
@Override
public ExecutionInfo getExecutionInfo() {
throw new UnsupportedOperationException(NOT_SUPPORTED);
}
/*
* (non-Javadoc)
* @see com.datastax.driver.core.ResultSet#all()
*/
@Override
public List<Row> all() {
throw new UnsupportedOperationException(NOT_SUPPORTED);
}
/*
* (non-Javadoc)
* @see com.datastax.driver.core.ResultSet#fetchMoreResults()
*/
@Override
public ListenableFuture<ResultSet> fetchMoreResults() {
throw new UnsupportedOperationException(NOT_SUPPORTED);
}
/*
* (non-Javadoc)
* @see com.datastax.driver.core.ResultSet#iterator()
*/
@Override
public Iterator<Row> iterator() {
throw new UnsupportedOperationException(NOT_SUPPORTED);
}
/*
* (non-Javadoc)
* @see com.datastax.driver.core.ResultSet#one()
*/
@Override
public Row one() {
throw new UnsupportedOperationException(NOT_SUPPORTED);
}
/*
* (non-Javadoc)
* @see com.datastax.driver.core.ResultSet#wasApplied()
*/
@Override
public boolean wasApplied() {
throw new UnsupportedOperationException(NOT_SUPPORTED);
}
}

View File

@@ -1,12 +1,12 @@
/*
* Copyright 2013-2014 the original author or authors.
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -19,7 +19,7 @@ import org.springframework.dao.QueryTimeoutException;
/**
* Spring data access exception for a Cassandra read timeout.
*
*
* @author Matthew T. Adams
*/
public class CassandraReadTimeoutException extends QueryTimeoutException {
@@ -28,8 +28,8 @@ public class CassandraReadTimeoutException extends QueryTimeoutException {
private boolean wasDataReceived;
public CassandraReadTimeoutException(boolean wasDataReceived, String msg, Throwable cause) {
super(msg);
public CassandraReadTimeoutException(boolean wasDataReceived, String message, Throwable cause) {
super(message, cause);
this.wasDataReceived = wasDataReceived;
}

View File

@@ -28,12 +28,18 @@ import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.cassandra.support.CassandraExceptionTranslator;
import org.springframework.cassandra.support.exception.CassandraReadTimeoutException;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import com.datastax.driver.core.ColumnDefinitions;
import com.datastax.driver.core.ConsistencyLevel;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.exceptions.ReadTimeoutException;
import com.datastax.driver.core.querybuilder.Select;
/**
* The CqlTemplateUnitTests class is a test suite of test cases testing the contract and functionality of the
@@ -46,19 +52,86 @@ import com.datastax.driver.core.Session;
@SuppressWarnings("unchecked")
public class CqlTemplateUnitTests {
@Rule public ExpectedException exception = ExpectedException.none();
@Rule
public ExpectedException exception = ExpectedException.none();
private CqlTemplate template;
@Mock private Session mockSession;
@Mock
private Session mockSession;
@Before
public void setup() {
template = new CqlTemplate(mockSession);
template.setExceptionTranslator(new CassandraExceptionTranslator());
}
@Test
public void doExecuteInSessionCallbackIsCalled() {
String result = template.doExecute(new SessionCallback<String>() {
@Override public String doInSession(Session session) throws DataAccessException {
session.execute("test");
return "test";
}
});
assertThat(result, is(equalTo("test")));
verify(mockSession, times(1)).execute(eq("test"));
}
@Test
public void doExecuteInSessionCallbackTranslatesException() {
exception.expect(CassandraReadTimeoutException.class);
exception.expectCause(org.hamcrest.Matchers.isA(ReadTimeoutException.class));
template.doExecute(new SessionCallback<String>() {
@Override public String doInSession(Session session) throws DataAccessException {
throw new ReadTimeoutException(ConsistencyLevel.ALL, 0, 1, true);
}
});
}
@Test
public void doExecuteWithNullSessionCallbackThrowsIllegalArgumentException() {
exception.expect(IllegalArgumentException.class);
exception.expectCause(is(nullValue(Throwable.class)));
exception.expectMessage("SessionCallback must not be null");
template.doExecute((SessionCallback) null);
}
@Test
public void doExecuteQueryReturnsResultSetForOqlQueryString() {
ResultSet mockResultSet = mock(ResultSet.class);
when(mockSession.execute(eq("SELECT * FROM Customers"))).thenReturn(mockResultSet);
ResultSet resultSet = template.doExecuteQueryReturnResultSet("SELECT * FROM Customers");
assertThat(resultSet, is(equalTo(mockResultSet)));
verify(mockSession, times(1)).execute(eq("SELECT * FROM Customers"));
verifyZeroInteractions(mockResultSet);
}
@Test
public void doExecuteSelectReturnsResultSetForOqlQueryString() {
Select mockSelect = mock(Select.class);
ResultSet mockResultSet = mock(ResultSet.class);
when(mockSession.execute(eq(mockSelect))).thenReturn(mockResultSet);
ResultSet resultSet = template.doExecuteQueryReturnResultSet(mockSelect);
assertThat(resultSet, is(equalTo(mockResultSet)));
verify(mockSession, times(1)).execute(eq(mockSelect));
verifyZeroInteractions(mockResultSet);
}
/**
* @see DATACASS-286
* @see <a href="https://jira.spring.io/browse/DATACASS-286">DATACASS-286</a>
*/
@Test
public void firstColumnToObjectReturnsColumnValue() {
@@ -74,12 +147,11 @@ public class CqlTemplateUnitTests {
when(mockIterator.next()).thenReturn(mockColumnDefinition);
template = new CqlTemplate() {
@Override
<T> T columnToObject(Row row, ColumnDefinitions.Definition columnDefinition) {
assertThat(row, is(sameInstance(mockRow)));
assertThat(columnDefinition, is(sameInstance(mockColumnDefinition)));
return (T) "test";
}
};
@@ -94,7 +166,7 @@ public class CqlTemplateUnitTests {
}
/**
* @see DATACASS-286
* @see <a href="https://jira.spring.io/browse/DATACASS-286">DATACASS-286</a>
*/
@Test
public void firstColumnToObjectReturnsNull() {
@@ -116,7 +188,7 @@ public class CqlTemplateUnitTests {
}
/**
* @see DATACASS-286
* @see <a href="https://jira.spring.io/browse/DATACASS-286">DATACASS-286</a>
*/
@Test
public void processOneIsSuccessful() {
@@ -138,7 +210,7 @@ public class CqlTemplateUnitTests {
}
/**
* @see DATACASS-286
* @see <a href="https://jira.spring.io/browse/DATACASS-286">DATACASS-286</a>
*/
@Test
public void processOneThrowsIncorrectResultSetSizeDataAccessExceptionWhenNoRowsFound() {
@@ -149,7 +221,6 @@ public class CqlTemplateUnitTests {
when(mockResultSet.one()).thenReturn(null);
try {
exception.expect(IncorrectResultSizeDataAccessException.class);
exception.expectCause(is(nullValue(Throwable.class)));
exception.expectMessage(containsString("expected 1, actual 0"));
@@ -164,7 +235,7 @@ public class CqlTemplateUnitTests {
}
/**
* @see DATACASS-286
* @see <a href="https://jira.spring.io/browse/DATACASS-286">DATACASS-286</a>
*/
@Test
public void processOneThrowsIncorrectResultSetSizeDataAccessExceptionWhenTooManyRowsFound() {
@@ -177,7 +248,6 @@ public class CqlTemplateUnitTests {
when(mockResultSet.isExhausted()).thenReturn(false);
try {
exception.expect(IncorrectResultSizeDataAccessException.class);
exception.expectCause(is(nullValue(Throwable.class)));
exception.expectMessage("ResultSet size exceeds 1");
@@ -193,7 +263,7 @@ public class CqlTemplateUnitTests {
}
/**
* @see DATACASS-286
* @see <a href="https://jira.spring.io/browse/DATACASS-286">DATACASS-286</a>
*/
@Test
public void processOnePassingNullResultSetThrowsIllegalArgumentException() {
@@ -201,7 +271,6 @@ public class CqlTemplateUnitTests {
RowMapper mockRowMapper = mock(RowMapper.class);
try {
exception.expect(IllegalArgumentException.class);
exception.expectCause(is(nullValue(Throwable.class)));
@@ -212,7 +281,7 @@ public class CqlTemplateUnitTests {
}
/**
* @see DATACASS-286
* @see <a href="https://jira.spring.io/browse/DATACASS-286">DATACASS-286</a>
*/
@Test
public void processOneWithRequiredTypeIsSuccessful() {
@@ -242,7 +311,7 @@ public class CqlTemplateUnitTests {
}
/**
* @see DATACASS-286
* @see <a href="https://jira.spring.io/browse/DATACASS-286">DATACASS-286</a>
*/
@Test
public void processOneWithRequiredTypeThrowsIncorrectResultSetSizeDataAccessExceptionWhenNoRowsFound() {
@@ -252,7 +321,6 @@ public class CqlTemplateUnitTests {
when(mockResultSet.one()).thenReturn(null);
try {
exception.expect(IncorrectResultSizeDataAccessException.class);
exception.expectCause(is(nullValue(Throwable.class)));
exception.expectMessage(containsString("expected 1, actual 0"));
@@ -266,7 +334,7 @@ public class CqlTemplateUnitTests {
}
/**
* @see DATACASS-286
* @see <a href="https://jira.spring.io/browse/DATACASS-286">DATACASS-286</a>
*/
@Test
public void processOneWithRequiredTypeThrowsIncorrectResultSetSizeDataAccessExceptionWhenTooManyRowsFound() {
@@ -278,7 +346,6 @@ public class CqlTemplateUnitTests {
when(mockResultSet.isExhausted()).thenReturn(false);
try {
exception.expect(IncorrectResultSizeDataAccessException.class);
exception.expectCause(is(nullValue(Throwable.class)));
exception.expectMessage(containsString("ResultSet size exceeds 1"));
@@ -293,11 +360,10 @@ public class CqlTemplateUnitTests {
}
/**
* @see DATACASS-286
* @see <a href="https://jira.spring.io/browse/DATACASS-286">DATACASS-286</a>
*/
@Test
public void processOneWithRequiredTypePassingNullResultSetThrowsIllegalArgumentException() {
exception.expect(IllegalArgumentException.class);
exception.expectCause(is(nullValue(Throwable.class)));

View File

@@ -0,0 +1,109 @@
/*
* Copyright 2013-2016 the original author or authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cassandra.core.support;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import java.util.Collections;
import java.util.Iterator;
import org.junit.Test;
import com.datastax.driver.core.ExecutionInfo;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;
/**
* Test suite of test cases testing the contract and functionality of the {@link EmptyResultSet}.
*
* @author John Blum
* @see org.springframework.cassandra.core.support.EmptyResultSet
* @since 1.5.0
*/
public class EmptyResultSetUnitTests {
@Test
public void nullSafeResultSetReturnsGivenResultSet() {
ResultSet mockResultSet = mock(ResultSet.class);
ResultSet theResultSet = EmptyResultSet.nullSafeResultSet(mockResultSet);
assertThat(theResultSet, is(sameInstance(mockResultSet)));
}
@Test
public void nullSAfeResultSetReturnsEmptyResultSetForNull() {
ResultSet resultSet = EmptyResultSet.nullSafeResultSet(null);
assertThat(resultSet, is(instanceOf(EmptyResultSet.class)));
}
@Test
public void isExhaustedForEmptyResultIsTrue() {
assertThat(EmptyResultSet.nullSafeResultSet(null).isExhausted(), is(true));
}
@Test
public void isFullyFetchedForEmptyResultSetIsTrue() {
assertThat(EmptyResultSet.nullSafeResultSet(null).isFullyFetched(), is(true));
}
@Test
public void getAllExecutionInfoForEmptyResultSetIsEmptyList() {
assertThat(EmptyResultSet.nullSafeResultSet(null).getAllExecutionInfo(),
is(equalTo(Collections.<ExecutionInfo>emptyList())));
}
@Test(expected = UnsupportedOperationException.class)
public void getColumnDefinitionsForEmptyResultSetThrowsUnsupportedOperationException() {
EmptyResultSet.nullSafeResultSet(null).getColumnDefinitions();
}
@Test
public void getExecutionInfoForEmptyResultSetIsNull() {
assertThat(EmptyResultSet.nullSafeResultSet(null).getExecutionInfo(), is(nullValue(ExecutionInfo.class)));
}
@Test
public void allForEmptyResultSetIsEmptyList() {
assertThat(EmptyResultSet.nullSafeResultSet(null).all(), is(equalTo(Collections.<Row>emptyList())));
}
@Test(expected = UnsupportedOperationException.class)
public void fetchMoreResultsFromEmptyResultSetThrowsUnsupportedOperationException() {
EmptyResultSet.nullSafeResultSet(null).fetchMoreResults();
}
@Test
public void iteratorForEmptyResultSetIsEmptyIterator() {
Iterator<Row> iterator = EmptyResultSet.nullSafeResultSet(null).iterator();
assertThat(iterator, is(notNullValue(Iterator.class)));
assertThat(iterator.hasNext(), is(false));
}
@Test
public void oneForEmptyResultSetIsNull() {
assertThat(EmptyResultSet.nullSafeResultSet(null).one(), is(nullValue(Row.class)));
}
@Test(expected = UnsupportedOperationException.class)
public void wasAppliedOnEmptyResultSetThrowsUnsupportedOperationException() {
EmptyResultSet.nullSafeResultSet(null).wasApplied();
}
}