我有一个名为MyClass
的班级。我在该课程中有一个方法,public int getSpacing()
。
我正在测试来自不同类的方法。 public static ArrayList<SpecialObject> getSpecialObjects()
。
getSpecialObjects()
在getSpacing()
的实例上调用MyClass
。当我使用Mockito运行测试时,我希望此方法始终返回0。我怎样才能做到这一点?在模拟方法之前,我发现的所有示例都需要一个对象的特定实例。
这就是我所知道的。
MyClass myInstance = new MyClass();
Mockito.when(myInstance.getSpacing()).thenReturn(0);
但是,我想覆盖getSpacing()
的所有实例的MyClass
行为,因为实例是在getSpecialObjects()
中动态创建的。我怎么能这样做?
这就是我想说的,但不知道如何。
Mockito.when((Any instance of MyClass).getSpacing()).thenReturn(0);
答案 0 :(得分:1)
您可以使用powermock模拟MyClass
构造函数,如下所示:
MyClass myClassSpy = spy(new MyClass());
whenNew(MyClass.class).withAnyArguments().thenReturn(myclassSpy);
然后你可以使用间谍的常规覆盖从该方法返回任何你喜欢的东西。不要忘记PrepareForTest
MyClass
答案 1 :(得分:1)
你不能像你所描述的那样纯粹在Mockito这样做。 Mockito不控制MyClass类型的所有对象,而是使得创建和实例化它可以控制的代理子类非常容易。这就是为什么Mockito依赖于非最终的类和方法,以及为什么你不能使用Mockito来影响所有实例的行为。
另请参阅: How to use Mockito when we cannot pass a mock object to an instance of a class
一种解决方法是切换库:As Slava describes,您可以使用PowerMock,它具有修改字节码的自定义类加载器,其中包括替换对new MyClass()
构造函数的调用,以便它们可以返回您的模拟。
作为替代方案,您可以重新构建类以使其更容易测试。您可以完全构造用于依赖注入的类并注入Provider<MyClass>
,但是有一个更本地化的解决方案具有大部分好处:
public class ClassThatConsumesMyClass {
/** Visible for testing. Override to customize MyClass instances. */
MyClass createMyClass() {
return new MyClass();
}
public ReturnValue getSpecialObjects(int n) {
for (int i = 0; i < n; i++) {
// Instead of calling "new MyClass()", call your method.
MyClass myClassInstance = createMyClass();
// ...
}
// ...
}
}
public class TestForClassThatConsumesMyClass {
ClassThatConsumesMyClass consumer;
@Before public void createMyClass() {
consumer = new ClassThatConsumesMyClass() {
@Override MyClass createMyClass() {
MyClass myInstance = Mockito.mock(MyClass.class);
Mockito.when(myInstance.getSpacing()).thenReturn(0);
return myInstance;
}
}
}
// Test as usual, now that you've mocked every newly-created
// instance of MyClass in your consumer.
}