次のコードとほぼ同等のコードがあります。
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
バグがあることがわかりました。上で示したコードの簡略化されたバージョンでは、バグは存在しません。
したがって、バグを修正することを決定し、の単体テストを実装するとしますMyCallable
。私の質問はこれです。MyCallable
内部クラスの単体テストをどの程度正確に記述しますか?
私自身の解決策は、最初にリファクタリングMyCallable
してConcreteThread
。MyCallable
は独自のファイルでパブリッククラスになり、内部クラスのプライベート変数へのアクセスに依存するのではなくConcreteThread
、DAO、Services、およびSingletonをコンストラクター引数として渡すようになりました。MyCallable
次に、単体テストでEasyMockを多用して、これらの依存関係をモックし、期待どおりに呼び出されていることを確認しました。
これらすべての結果として、のコードMyCallable
は以前よりもいくらか大きくなります。のプライベート変数にアクセスできなくなったため、コンストラクターの引数としてそれらを渡し、プライベート変数として設定する必要がありConcreteThread
ます。ConcreteThread
MyCallable
これは間違ったアプローチだったと思いますか?それはおそらく、この種のリファクタリングを実行することによって、カプセル化を破り、コードベースに不要な定型文を追加したのでしょうか?代わりに、テストでリフレクションを使用しましたか?