Шаблон 2 — шаблон фабричного помощника
Один из случаев, когда этот шаблон не будет работать, — это если MyClass является окончательным. Большая часть фреймворка Mockito не очень хорошо работает с конечными классами; и это включает использование spy(). Другой случай, когда MyClass где-то использует getClass() и требует, чтобы результирующее значение было MyClass. Это не сработает, потому что класс шпиона на самом деле является сгенерированным Mockito подклассом исходного класса.
В любом из этих случаев вам понадобится немного более надежный шаблон помощника фабрики, как показано ниже.
public class MyClass{
static class FactoryHelper{
Foo makeFoo( A a, B b, C c ){
return new Foo( a, b, c );
}
}
//...
private FactoryHelper helper;
public MyClass( X x, Y y ){
this( x, y, new FactoryHelper());
}
MyClass( X x, Y, y, FactoryHelper helper ){
//...
this.helper = helper;
}
//...
Foo foo = helper.makeFoo( a, b, c );
}
Итак, у вас есть специальный конструктор, предназначенный только для тестирования, с дополнительным аргументом. Это используется из вашего тестового класса при создании объекта, который вы собираетесь тестировать. В своем тестовом классе вы издеваетесь над классом FactoryHelper, а также над объектом, который хотите создать.
@Mock private MyClass.FactoryHelper mockFactoryHelper;
@Mock private Foo mockFoo;
private MyClass toTest;
и вы можете использовать его так
toTest = new MyClass( x, y, mockFactoryHelper );
when( mockFactoryHelper.makeFoo(
any( A.class ), any( B.class ), any( C.class )))
.thenReturn( mockFoo );