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


302

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

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

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

我可以写:

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

但是明显的问题是,getBar()从来没有使用与Bazoo我存根方法相同的对象来调用它。(请该new运算符!)

如果我可以以不myFoo考虑参数的方式返回该方法的方法来对它进行存根,我将非常喜欢。失败的话,我会听取其他解决方法的建议,但我真的想避免更改生产代码,直到有合理的测试范围为止。

Answers:


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

或(避免nulls):

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

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

对于Mockito 2.1.0及更高版本:

import static org.mockito.ArgumentMatchers.*;

对于旧版本:

import static org.mockito.Matchers.*;

2
当答案在“接受答案冻结”结束之前,我喜欢它。
埃里克·威尔逊

10
有一个notNull(Bazoo.class)就像any(Bazoo.class)(也许它没有在这个答案的时间存在)
Dandre佳佳

2
我有一个稍微特殊的情况,我可以有两个可能的参数之一,Bazoo或者Cazoo它们都是的子类Azoo。因为Bazoo我需要返回foo,但是因为Cazoo我需要返回bar。在这种情况下,建议的Matchers.any()解决方案不起作用,但是Matchers.isA()效果很好。
Tanvir

3
org.mockito.Matchers现在已弃用- org.mockito.ArgumentMatchers改为使用,即import static org.mockito.ArgumentMatchers.*(请参阅文档
DontDivideByZero

when(myFoo.knowsWhatsUp()).thenReturn(myMoney);
6rchid

18

像这样使用:

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

在需要导入之前 Mockito.Matchers


1
这简直太棒了!
DrB


1

另一种选择是依靠良好的旧时尚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。对于这种情况,您不能轻松地在模拟代码中构造预期的参数对象。

另一种可能的方法是使用Answer可与该when方法一起使用的Mockito 对象。 Answer使您可以拦截实际的调用并检查输入参数并返回模拟对象。在下面的示例中,我any用于捕获对模拟方法的任何请求。但是然后在Answerlambda中,我可以进一步检查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检查的说法。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.