Mockito可以存根方法而不考虑参数?

我试图测试一些遗留代码,使用Mockito。

我想存根在生产中使用的FooDao,如下所示:

foo = fooDao.getBar(new Bazoo());

我可以这样写:

when(fooDao.getBar(new Bazoo())).thenReturn(myFoo);

但明显的问题是,getBar()从未被调用与我为该方法存根的相同的Bazoo对象。(该死的new操作符!)

如果我可以存根该方法,无论参数如何,它都会返回myFoo,我会很喜欢。如果做不到这一点,我将听取其他解决方案的建议,但我真的希望在有合理的测试覆盖率之前避免更改生产代码。

279340 次浏览

http://site.mockito.org/mockito/docs/1.10.19/org/mockito/Matchers.html

anyObject()应该适合你的需要。

另外,你总是可以考虑为Bazoo类实现hashCode()equals()。这将使您的代码示例按您希望的方式工作。

when(
fooDao.getBar(
any(Bazoo.class)
)
).thenReturn(myFoo);

or(避免__abc0):

when(
fooDao.getBar(
(Bazoo)notNull()
)
).thenReturn(myFoo);

不要忘记导入匹配器(许多其他的匹配器可用):

对于Mockito 2.1.0及更新版本:

import static org.mockito.ArgumentMatchers.*;

对于旧版本:

import static org.mockito.Matchers.*;

像这样使用:

when(
fooDao.getBar(
Matchers.<Bazoo>any()
)
).thenReturn(myFoo);

在你需要导入Mockito.Matchers之前

另一个选择是依赖传统的equals方法。只要when模拟equals中的参数是被测试代码中的参数,那么Mockito将匹配模拟。

这里有一个例子。

public class MyPojo {


public MyPojo( String someField ) {
this.someField = someField;
}


private String someField;


@Override
public boolean equals( Object o ) {
if ( this == o ) return true;
if ( o == null || getClass() != o.getClass() ) return false;
MyPojo myPojo = ( MyPojo ) o;
return someField.equals( myPojo.someField );
}


}

然后,假设你知道someField的值是什么,你可以像这样模拟它。

when(fooDao.getBar(new MyPojo(expectedSomeField))).thenReturn(myFoo);

优点:这比any匹配器更显式。作为代码的审查者,我在初级开发人员编写的代码中密切注意any,因为它会检查他们的代码逻辑以生成传递的适当对象。

弊:有时传递给对象的字段是一个随机ID。对于这种情况,在模拟代码中不容易构造预期的参数对象。

另一种可能的方法是使用Mockito的Answer对象,该对象可以与when方法一起使用。Answer让你拦截实际调用,检查输入参数并返回一个模拟对象。在下面的例子中,我使用any来捕获对被模拟方法的任何请求。但随后在Answer lambda中,我可以进一步检查Bazo参数…也许是为了验证传递给它的ID是否正确。我更喜欢这个而不是any本身,这样至少会对实参进行一些检查。

    Bar mockBar = //generate mock Bar.


when(fooDao.getBar(any(Bazo.class))
.thenAnswer(  ( InvocationOnMock invocationOnMock) -> {
Bazo actualBazo = invocationOnMock.getArgument( 0 );


//inspect the actualBazo here and thrw exception if it does not meet your testing requirements.
return mockBar;
} );

综上所述,我喜欢依赖equals(其中期望的实参和实际实参应该彼此相等),如果不可能存在相等(由于无法预测实际实参的状态),我将使用Answer来检查实参。