Witajcie,
Uczę się uprawiać TDD. Moja klasa i testy:
public class DatabaseHelperImpl implements DatabaseHelper {
private DataSource dataSource;
public DatabaseHelperImpl(DataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public <T> List<T> select(String query, RowMapper<T> rowMapper, Object... params) {
try (Connection connection = this.dataSource.getConnection()) {
try (PreparedStatement preparedStatement = connection.prepareStatement(query)) {
try (ResultSet resultSet = preparedStatement.executeQuery()) {
List<T> result = new ArrayList<>();
while (resultSet.next()) {
result.add(rowMapper.map(resultSet));
}
return result;
}
}
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
}
}
@RunWith(MockitoJUnitRunner.class)
public class DatabaseHelperTest {
@Mock
private DataSource dataSource;
@Mock
private Connection connection;
@Mock
private PreparedStatement preparedStatement;
private DatabaseHelper databaseHelper;
@Before
public void init() {
this.databaseHelper = new DatabaseHelperImpl(dataSource);
}
@Test(expected = RuntimeException.class)
public void shouldThrowExceptionOnConnectionCreationFailed() throws SQLException {
when(this.dataSource.getConnection()).thenThrow(new SQLException("dummy exception"));
this.databaseHelper.select("", resultSet -> new Object());
}
@Test(expected = RuntimeException.class)
public void shouldThrowExceptionOnPreparedStatementCreationFailed() throws SQLException {
when(this.dataSource.getConnection()).thenReturn(this.connection);
when(this.connection.prepareStatement(any(String.class))).thenThrow(new SQLException("Dummy exception"));
this.databaseHelper.select("", resultSet -> new Object());
}
@Test
public void shouldPrepareStatementWithGivenQuery() throws SQLException {
String query = "Sample query";
when(this.dataSource.getConnection()).thenReturn(this.connection);
when(this.connection.prepareStatement(any(String.class))).thenReturn(this.preparedStatement);
when(this.preparedStatement.executeQuery()).thenReturn(Mockito.mock(ResultSet.class));
this.databaseHelper.select(query, resultSet -> new Object());
verify(this.connection, atLeastOnce()).prepareStatement(eq(query));
}
@Test
public void shouldMapRowWithResultSet() throws SQLException {
ResultSetSavingRowMapper resultSetSavingRowMapper = new ResultSetSavingRowMapper();
ResultSet result = Mockito.mock(ResultSet.class);
when(result.next()).thenAnswer(new Answer<Boolean>() {
private boolean first = true;
@Override
public Boolean answer(InvocationOnMock invocationOnMock) throws Throwable {
boolean val = this.first;
this.first = !this.first;
return val;
}
});
when(this.dataSource.getConnection()).thenReturn(this.connection);
when(this.connection.prepareStatement(any(String.class))).thenReturn(this.preparedStatement);
when(this.preparedStatement.executeQuery()).thenReturn(result);
this.databaseHelper.select("", resultSetSavingRowMapper);
assertEquals(result, resultSetSavingRowMapper.getResultSet());
}
public class ResultSetSavingRowMapper implements DatabaseHelper.RowMapper<Object> {
@Setter
@Getter
private Object returnValue = new Object();
@Getter
private ResultSet resultSet;
@Override
public Object map(ResultSet resultSet) {
this.resultSet = resultSet;
return this.returnValue;
}
}
}
I tutaj pojawia się moje pytanie.
Testy powinny być aż tak dokładne? Jeżeli nie to które są zbędne?
Testy powinny zajmować więcej miejsca od kodu?
Co w nich poprawić?