我有一段代碼大致等同於以下內容。重構測試
public class ConcreteThread extends OtherThread {
private DAOfirst firstDAO;
private DAOsecond secondDAO;
private TransformService transformService;
private NetworkService networkService;
public ConcreteThread(DAOfirst first, DAOsecond second, TransformService service1,
NetworkService service2) {
firstDAO = first;
secondDAO = second;
transformService = service1;
networkService = service2;
}
public Future go() {
Results r1 = firstDAO.getResults();
MyCallable c1 = new MyCallable(r1);
return super.getThreadPool().submit(c1);
}
private class MyCallable implements Callable {
private Results result;
private Long count;
private MyCallable(Results r) {
this.result = r;
this.count = new Long(0);
}
public Long call() {
Singleton transactions = Singleton.getInstance();
try {
transactions.begin();
while(result != null) {
Transformed t = transformService.transform(r1);
networkService.sendSomewhere(t);
count = count += result.size();
secondDao.persist(result);
result = firstDao.getNext(result);
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
transactions.end();
}
}
}
無論這些類(內或外)的有單元測試,並將其結果是內部類,MyCallable
,在它的一個錯誤。在上面給出的代碼的簡化版本中,該錯誤不存在。
因此,讓我們假設您決定修復這個bug,併爲MyCallable
執行一些單元測試。我的問題是這個;你將如何去編寫MyCallable
內部類的單元測試?
我自己的解決方案是首先重構MyCallable
和ConcreteThread
。 MyCallable
在其自己的文件中被創建爲公共類,並且ConcreteThread
現在將DAO,Services和Singleton作爲構造函數參數傳遞給MyCallable
,而不是依賴內部類訪問它的私有變量。
然後,我在單元測試中大量使用EasyMock來模擬這些依賴關係,並驗證它們是否以我期望的方式被調用。
所有這一切的結果是MyCallable
的代碼比它更大一些。因爲它不再有權訪問ConcreteThread
中的私有變量,所以ConcreteThread
必須在構造函數中將它們作爲參數傳入,並且MyCallable
將它們設置爲私有變量。
你認爲這是錯誤的做法嗎?也許通過執行這種重構,我已經破解了封裝並向代碼庫添加了不必要的樣板文件?你會在測試中使用反射嗎?
+1完全同意。關於封裝,只要你保持你的MyCallable包是本地的(就像Augusto所說的那樣),你並沒有打破封裝,只是放鬆它來幫助測試,這是很常見的做法。你可能希望在某處發表評論。至於樣板,它不會真的增加代碼的複雜性,所以不要太擔心。稍微多一些的代碼比沒有測試的代碼更好。 – rodion 2011-02-18 12:01:32