有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java可以在不考虑参数的情况下模拟方法吗?

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

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

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

我可以写:

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

但是明显的问题是getBar()从来没有使用我为之存根的相同Bazoo对象调用过。(诅咒那个new操作符!)

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


共 (4) 个答案

  1. # 1 楼答案

    这样使用:

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

    在需要导入Mockito.Matchers之前

  2. # 3 楼答案

    另一种选择是依赖于良好的旧式equals方法。只要whenmockequals中的参数与被测试代码中的参数相同,Mockito就会与mock匹配

    这里有一个例子

    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捕获对被模拟方法的任何请求。但是在{}lambda中,我可以进一步检查Bazo论点。。。也许是为了验证传递给它的ID是否正确。我更喜欢这个,而不是它本身,这样至少可以对这个论点进行一些检查

        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来检查参数

  3. # 4 楼答案

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

    或者(为了避免null):

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

    别忘了导入匹配器(还有许多其他匹配器):

    对于Mockito 2.1.0及更新版本:

    import static org.mockito.ArgumentMatchers.*;
    

    对于旧版本:

    import static org.mockito.Matchers.*;