我正在用mockito測試一個簡單的DAO層,但是我發現一個問題,基本上是一個難以測試的界面,我想知道您是否可以給我一些洞見...需要重構才能提高可測試性
這是我要測試的方法:
public Person getById(UserId id) {
final Person person = new PersonImpl();
gateway.executeQuery(GET_SQL + id.getUserId(), new ResultSetCommand(){
public int work(ResultSet rs) throws SQLException {
if(rs.next()){
person.getName().setGivenName(rs.getString("name"));
person.getName().setFamilyName(rs.getString("last_name"));
}
return 0;
}
});
return person;
}
我使用DatabaseGateway這是我的Java代碼和SQL之間的接口,並且該方法接受一個匿名類,這是網關的方法的executeQuery:
public int executeQuery(String sql, ResultSetCommand cmd) {
try{
Connection cn = createConnection();
PreparedStatement st = cn.prepareStatement(sql);
int result = cmd.work(st.executeQuery());
cn.close();
return result;
}catch(Exception e){
throw new RuntimeException("Cannot Create Statement for sql " + sql,e);
}
}
問題在於,由於那個匿名類,測試PersonDAO變得越來越困難。
我可以重構整個代碼,甚至可以刪除匿名類,如果有人提出更好的設計(我敢肯定有更簡單的一個,但我似乎無法找到它)。
謝謝大家的建議。
PD:如果您需要了解更多信息,請隨時問
編輯:測試這是很難做到的
public void testGetPersonById(){
DatabaseGateway gateway = mock(DatabaseGateway.class);
when(gateway.executeQuery(anyString(),any(ResultSetCommand.class)));
PersonDAO person_dao = new PersonDAOImpl(gateway);
Person p = person_dao.getById(new UserId(Type.viewer,"100"));
}
看到了嗎? ResultCommand是模擬的一部分,我也對測試代碼感興趣...我應該對該特定命令做一個單獨的測試嗎?
請給出一個越來越難做的測試的例子。 – 2009-07-17 14:24:35
我不太瞭解Java,但我會說ResultSetCommand不相關。您正在測試getPersonById,以確保在給定有效的UserId時返回正確的Person,在給定無效的時候拋出異常等。如果它正常工作,則不關心它使用特定的ResultSetCommand。 – 2009-07-17 14:35:39