我正在尝试模拟一个抽象类,但是从我所看到的来看,我认为这是不可能的.我们有一些使用泛型的类,它们必须扩展特定的抽象类.他们中有一整群人,他们已被成功嘲笑.抽象类有一个处理返回泛型的方法,如下所示:
public abstract class ChildPresenter <T extends ChildView> {
private T view;
public abstract T getView();
}
我们正在测试的类包含以下内容:
public class ParentPresenter {
private ConcreteChildPresenter1 childPresenter1;
private ConcreteChildPresenter2 childPresenter2;
private ConcreteChildPresenter3 childPresenter3;
private ConcreteChildPresenter4 childPresenter4;
List<ChildPresenter> childPresenters;
}
在构造函数中,这些类使用Google Guice注入,设置为变量,并添加到子演示者列表中.
被测试的方法是一种迭代所有childPresenters对象并运行方法getView()的方法.
我在测试课程中尝试了这种方式:
public class ParentPresenterTest {
private ConcreteChildPresenter1 childPresenter1;
private ConcreteChildPresenter2 childPresenter2;
private ConcreteChildPresenter3 childPresenter3;
private ConcreteChildPresenter4 childPresenter4;
private List<ChildPresenter> childPresenters;
//This is an abstract class
private ChildView childView;
@BeforeTest
public void createInjector() {
Guice.createInjector(...//Creates a fake module and does binding for the variables mentioned earlier
//e.g.
childPresenter1 = mock(ConcreteChildPresenter1.class);
binder.bind(ConcreteChildPresenter1.class).toInstance(childPresenter1);
//e.t.c for other variables
//Same for child view
childView = mock(ChildView.class);
binder.bind(ChildView.class).toInstance(childView);
}
childPresenters = new ArrayList<ChildPresenter>();
childPresenters.add(childPresenter1);
//Add all child presenters
for(ChildPresenter childPresenter : childPresenters) {
when(childPresenter.getView()).thenReturn(childView);
}
}
}
问题发生在when(childPresenter.getView()).thenReturn(childView);由于Mockito抱怨以下消息:
org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
ChildView$$EnhancerByMockitoWithCGLIB$$2f6a4bd5
cannot be returned by getView() getView() should return ConcreteChildView1
*** If you’re unsure why you’re getting above error read on. Due to the nature of the syntax above problem might occur because:
This exception might occur in wrongly written multi-threaded tests. Please refer to Mockito FAQ on limitations of concurrency testing.
A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.
我能理解,但是当我想做的是使用以下方法确认模拟的ChildView称为单个方法时,模拟每个具体的ChildView似乎很浪费:
verify(childView, atLeast(childPresenters.size())).getView();
还有另一种方法吗?我可以以某种方式使用模拟的抽象类代替具体的抽象类吗?
编辑这是如何实现getView()方法的具体版本:
public ConcreteChildPresenter1<ConreteChildView1> {
@Override
public ConreteChildView1 getView() {
view.buildView();
return view;
}
}
还有所有子视图扩展的抽象ChildView类:
public abstract ChildView {
public abstract void buildView();
}
解决方法:
由于每个子提示者都返回特定类型的视图,因此,正如您已经了解的那样,您不能用抽象类ChildView的模拟代替它们.
只有在您提供正确的实现(如此处所述)的情况下,才有一种在运行时获取ChildView具体类型的方法:Get generic type of class at runtime
然后,您可以通过以下方式初始化演示者的模拟:
for(ChildPresenter childPresenter : childPresenters) {
//this getter returns the needed runtime class
when(childPresenter.getView()).thenReturn(mock(childPresenter.getViewType()));
}