我试图嘲笑一个抽象类,但从我所看到的,我不认为这是可能的。我们有一些使用泛型的类,它必须扩展特定的抽象类。他们中有一大群人,他们被成功嘲笑了。抽象类有一个处理返回泛型的方法,如下所示:
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
getView()不能返回getView()应该返回ConcreteChildView1
***如果您不确定为什么上述错误,请继续阅读。由于上述语法的性质,可能会出现问题,原因是:
此异常可能在错误编写的多线程测试中发生。有关并发性测试的限制,请参阅Mockito常见问题解答。
- 醇>
使用when(spy.foo())。then()语法时,间谍是存根的。使用doReturn | Throw()方法系列来存储间谍更安全。更多关于Mockito.spy()方法的javadocs。
我可以理解,但是当我想要做的就是使用以下内容确认被称为单个方法的模拟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();
}
答案 0 :(得分:2)
由于每个子演示者都返回一个特定类型的视图,因此您不能像您已经理解的那样用抽象类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()));
}
答案 1 :(得分:1)
根据改进,模拟的ChildView
基于错误的超类。我想你可以在Guice注射器上修复它:
Guice.createInjector(...//Creates a fake module and does binding for the variables mentioned earlier
// ...
//Same for child view
childView = mock(ConcreteChildPresenter1.class); // this is the fix
binder.bind(ChildView.class).toInstance(childView);
}