Mockito可以在不考虑参数的情况下存根方法吗?

时间:2011-05-11 19:35:36

标签: java unit-testing mocking mockito

我正在尝试使用Mockito测试一些遗留代码。

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

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

我可以写:

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

但显而易见的问题是getBar()永远不会使用我为该方法存根的Bazoo对象调用。 (诅咒new运营商!)

如果我能以一种不管参数的方式返回myFoo的方式来存根方法,我都会喜欢它。如果做不到这一点,我会听取其他解决方法的建议,但我真的希望避免更改生产代码,直到有合理的测试覆盖率。

4 个答案:

答案 0 :(得分:396)

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

或(以避免null s):

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

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

对于Mockito 2.1.0及更新版本:

import static org.mockito.ArgumentMatchers.*;

对于旧版本:

import static org.mockito.Matchers.*;

答案 1 :(得分:15)

像这样使用:

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

在您需要导入Mockito.Matchers

之前

答案 2 :(得分:12)

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

anyObject应该符合您的需求。

此外,您始终可以考虑为Bazoo类实现hashCode和equals。这将使您的代码示例按您希望的方式工作。

答案 3 :(得分:0)

另一种选择是依靠良好的旧式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持开放态度,因为它浏览了他们代码的逻辑以生成适当的传递对象。

con:有时传递给对象的字段是一个随机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来检查参数。