我正在嘗試爲某些打開數據庫連接並對數據庫執行一些操作的代碼編寫單元測試。我想斷言連接被正確關閉,即使拋出異常也是如此。當試圖使用資源時調用斷言關閉
我要測試的代碼如下所示:
public void methodToTest(final String aName) {
final String sqlDeleteStatement = "DELETE FROM " + DB_FULL_TABLE + " WHERE name=?";
try (final Connection connection = this.dataSource.getConnection();
final PreparedStatement deleteStatement = connection.prepareStatement(sqlDeleteStatement);) {
connection.setAutoCommit(true);
deleteStatement.setString(1, aName);
deleteStatement.executeUpdate();
}
catch (final SQLException e) {
// handle error
}
}
我目前使用JMock的創建數據源和連接對象實例模擬和仿真,一個例外是在connection.prepareStatement
拋出:
public void testConnectionClosed() throws Exception {
final Mockery mockery = new Mockery();
final DataSource dataSource = mockery.mock(DataSource.class);
final Connection connection = mockery.mock(Connection.class);
final String exceptionMessage = "intentionally thrown " + UUID.randomUUID();
mockery.checking(new Expectations() {{
oneOf(dataSource).getConnection();
will(returnValue(connection));
oneOf(connection).prepareStatement(with(any(String.class)));
will(throwException(new SQLException(exceptionMessage)));
oneOf(connection).close();
}});
final ClassUnderTest cut = new ClassUnderTest(dataSource);
cut.methodToTest("someName");
mockery.assertIsSatisfied();
}
我面臨的問題是,測試是綠色和沒有期望connection.close()
。沒有期待我看到一個抑制org.jmock.api.ExcpectationError
:
Suppressed: unexpected invocation: java.sql.Connection1370903230.close()
但隨着錯誤的嘗試,與資源語句隱含finally塊內提出的測試沒有失敗。
我不想重寫代碼只是爲了讓這個測試有意義,但我想確保正確的資源處理,而且不需要太多關於特定實現細節的知識,比如使用try-with-resource。
有沒有辦法用jMock來實現這一點?
不,我不是要求在圖書館推薦。所以請不要標記爲脫離主題。
我內部已經提出了對jMock的關注。我們的測試基地非常大,jMock在各地都有使用。由於它在99.9%的用例中工作正常,因此很難爭取框架切換並獲得批准。但是,我可以用mockito編寫一個像上面這樣的測試,並獲得所需的行爲? – dpr
關於測試好案例和進行錯誤案例正確處理的觀點:如果我這樣做了,我會在測試中添加大量不一定成立的假設。如果有人更改了實現並決定不再使用try-with-resource,而是關閉try-block中的連接,那麼好的情況仍然會成功,但連接在錯誤情況下將保持不變。那就是測試不會在所描述的重構中發現錯誤。 – dpr
當然。但是,如果有人打算**故意**的事情,你可以做的事情並不多。如果那個人不知道他在做什麼,那麼他可能會前進並「調整」那個失敗的測試,直到它給你「綠色」。是的,用Mockito或EasyMock編寫這個測試用例應該很簡單。 – GhostCat