У меня есть фрагмент кода, примерно эквивалентный следующему.
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
теперь передает DAOs, Services и Singleton в качестве аргументов конструктора для MyCallable
, а не полагается на доступ внутреннего класса к своим закрытым переменным.
Затем я активно использовал EasyMock в модульных тестах, чтобы смоделировать эти зависимости и убедиться, что они вызывались так, как я ожидал.
Следствием всего этого является то, что код для MyCallable
несколько больше, чем был. Поскольку он больше не имеет доступа к закрытым переменным в ConcreteThread
, ConcreteThread
должен передавать их в качестве аргументов в конструкторе, а MyCallable
устанавливает их как частные переменные.
Вы думаете, что это был неправильный подход? Что, возможно, выполнив такой рефакторинг, я нарушил инкапсуляцию и добавил ненужный шаблон к базе кода? Вы бы вместо этого использовали отражение в тестах?