I have these classes that have a boilerplate way of initialization. So, instead of writing it each time, I wrote a class called MockUtil.java
, and I put the boilerplate mocks in there.
MockUtil
has static variables and methods which can be called to do the mocking for the test classes. So, when writing a new test class setup, MockUtil
's setup, boilerplate expectations, replays, and verifications of mock are being called from the Test
class.
I feel like this reduces a lot of boiler-plate burden on the test classes. But, still feel like the code structure/code pattern can be improved. I am not sure if it has to be a util class or something else, because, two tests can't run simultaneously because of static variables and methods and I feel like it reduces the scope of enhancements if any that has to be done. Could you give me suggestions on what I can improve in my following code?
MockUtil.java
public class MockUtil {
public static JdbcTransactionImpl transaction;
public static Connection connection;
public static PreparedStatement statement;
public static ResultSet resultSet;
public static Connection getConnection() {
return connection;
}
public static ResultSet getResultSet() {
return resultSet;
}
public static PreparedStatement getStatement() {
return statement;
}
public static void createMocks() {
//more boilerplate mocks to create services to be used in each Test -- which are ignored here.
//boilerplate tx mocks
transaction = createMockBuilder(JdbcTransactionImpl.class)
.addMockedMethod("getConnection").createMock();
connection = createMock(Connection.class);
statement = createMock(PreparedStatement.class);
resultSet = createMock(ResultSet.class);
}
public static void setContextualExpectations(String...sqls) throws Exception {
//boilerplate tx expectations.
expect(context.getTransaction()).andReturn(transaction).anyTimes();
expect(transaction.getConnection()).andReturn(connection).anyTimes();
for(String sql: sqls) {
expect(connection.prepareStatement(sql)).andReturn(statement);
}
expect(statement.executeQuery()).andReturn(resultSet).anyTimes();
}
public static void setReplays() throws SQLException {
replay(transaction);
replay(connection);
replay(statement);
replay(resultSet);
}
public static void closeResources() throws SQLException {
//boilerplate resource closing.
statement.close();
resultSet.close();
}
public static void verifyMocks() {
//boilerplate verification of mocks.
verify(transaction);
verify(connection);
verify(statement);
verify(resultSet);
}
}
One of the several test classes
Class1Test
private void setCustomExpectationsForTest1XXX() throws SQLException {
PreparedStatement stmt = MockUtil.getStatement();
ResultSet rs = MockUtil.getResultSet();
checkExp(stmt, rs);
}
private void checkExp(PreparedStatement stmt, ResultSet rs)
throws SQLException {
stmt.setString(1, in.getCode());
expect(rs.next()).andReturn(true);
expect(rs.getString(1)).andReturn(customVal);
MockUtil.closeResources();
}
@Before
public void setUp() throws Exception {
MockUtil.createMocks();
createImportExportObj();
}
@After
public void tearDown() throws Exception {
in = null;
out = null;
}
@Test
public void test1XXX() throws Exception {
MockUtil.setContextualExpectations(calcPbValForGldSqls);
setCustomExpectationsForTest1XXX();
MockUtil.setReplays();
program.execute(in, out);
BigDecimal expected = new BigDecimal("85000").setScale(4);
BigDecimal actual = out.getAmt();
assertEquals(expected, actual);
MockUtil.verifyMocks();
}
}