Java 如何告诉Mockito mock对象在下次调用时返回不同的内容?
所以,我在类级别上创建一个模拟对象作为静态变量,就像这样。。。在一个测试中,我希望Java 如何告诉Mockito mock对象在下次调用时返回不同的内容?,java,unit-testing,junit,mocking,mockito,Java,Unit Testing,Junit,Mocking,Mockito,所以,我在类级别上创建一个模拟对象作为静态变量,就像这样。。。在一个测试中,我希望Foo.someMethod()返回一个特定的值,而在另一个测试中,我希望它返回一个不同的值。我遇到的问题是,似乎我需要重建模拟,以使其正常工作。我希望避免重建模拟,而只是在每个测试中使用相同的对象 class TestClass { private static Foo mockFoo; @BeforeClass public static void setUp() {
Foo.someMethod()
返回一个特定的值,而在另一个测试中,我希望它返回一个不同的值。我遇到的问题是,似乎我需要重建模拟,以使其正常工作。我希望避免重建模拟,而只是在每个测试中使用相同的对象
class TestClass {
private static Foo mockFoo;
@BeforeClass
public static void setUp() {
mockFoo = mock(Foo.class);
}
@Test
public void test1() {
when(mockFoo.someMethod()).thenReturn(0);
TestObject testObj = new TestObject(mockFoo);
testObj.bar(); // calls mockFoo.someMethod(), receiving 0 as the value
}
@Test
public void test2() {
when(mockFoo.someMethod()).thenReturn(1);
TestObject testObj = new TestObject(mockFoo);
testObj.bar(); // calls mockFoo.someMethod(), STILL receiving 0 as the value, instead of expected 1.
}
}
在第二个测试中,当调用testObj.bar()时,我仍然收到0作为值。。。解决这个问题的最佳方法是什么?请注意,我知道我可以在每个测试中使用不同的模拟
Foo
,但是,我必须将多个请求链接到mockFoo
,这意味着我必须在每个测试中进行链接。首先不要使模拟成为静态的。让它成为一个私人领域。只需将设置类放在@之前的,而不是@之前的类中。它可能有很多,但很便宜
其次,现在使用的方法是让模拟根据测试返回不同内容的正确方法。您也可以(2.8.9API中的#10)。在这种情况下,您将使用多个thenReturn调用或一个带有多个参数(varargs)的thenReturn调用
对于使用spy()和doReturn()而不是when()方法的用户:
在不同的调用中,您需要返回不同的对象:
doReturn(obj1).doReturn(obj2).when(this.spyFoo).someMethod();
对于经典模拟:
when(this.mockFoo.someMethod()).thenReturn(obj1, obj2);
或者在引发异常的情况下:
when(mockFoo.someMethod())
.thenReturn(obj1)
.thenThrow(new IllegalArgumentException())
.thenReturn(obj2, obj3);
对于所有搜索以返回某个内容,然后搜索另一个调用抛出异常的用户:
when(mockFoo.someMethod())
.thenReturn(obj1)
.thenReturn(obj2)
.thenThrow(new RuntimeException("Fail"));
或
或者,甚至更干净:
when(mockFoo.someMethod()).thenReturn(obj1, obj2);
我认为您还可以利用.thenReturn()接受varargs这一事实,因此代码可以缩短为:when(mockFoo.someMethod()).thenReturn(0,1,-1)@贾斯汀穆勒-这值得一个单独的答案,我认为(与评论相反)在这种情况下,这个答案是不正确的。如果将此方法存根为返回0和1,那么只要运行test1
然后运行test2
,就可以了。但是,您的持续集成环境可能会以其他顺序运行测试。或者,您可能希望自己运行test2
,而不首先运行test1
,在这种情况下,它将失败。单元测试必须始终相互独立;而且,各个测试之间不应该存在依赖关系,也不应该存在对特定测试顺序的依赖关系。而链接然后返回语句。。。。。。有它的用途,就像对单个使用varargs然后返回
一样,在这种特殊情况下,它不是正确的解决方案。在我看来,这里的选民群很可能没有理解这个问题。如果没有@FixMethodOrder
,Junit本身无法确保测试顺序。这应该是答案。
when(mockFoo.someMethod())
.thenReturn(obj1, obj2)
.thenThrow(new RuntimeException("Fail"));
when(mockFoo.someMethod()).thenReturn(obj1, obj2);