我正在尝试嘲笑一个抽象类,但是据我所知,我认为这是不可能的。我们有一些使用仿制药的类,必须扩展特定的抽象类。其中有一群,他们被成功地被嘲笑。抽象类具有一种涉及返回通用的方法,看起来像这样:
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 $$ eNANCERBYBYBYMOCKITOWITHCGLIB $$ 2F6A4BD5
无法通过getView()getView()返回ConcretechildView1
***如果您不确定为什么要继续阅读错误。由于语法的性质,上述问题可能会发生:
此异常可能发生在错误编写的多线程测试中。请参阅有关并发测试局限的Mockito常见问题。
间谍是使用(spy.foo())。然后()语法使用的。用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();
}
由于每个孩子都会返回特定类型的视图,因此您无法用抽象类Childview的模拟来代替它们。
只有在提供正确的实现时,才能在运行时获得混凝土类型的ChildView类型
然后,您可以以这种方式初始化演示者的模拟:
for(ChildPresenter childPresenter : childPresenters) {
//this getter returns the needed runtime class
when(childPresenter.getView()).thenReturn(mock(childPresenter.getViewType()));
}
基于改进,模拟的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);
}