Mockito:在void方法上填充不同的值



我正在使用Mockito进行单元测试。我需要模拟一个填充一些输入的void方法。非常天真的例子:

class Something {
   AnotherThing thing = new AnotherThing();
   public int doSomething(Stuff stuff)
   {
      thing.doThing(stuff);
      if(thing.getName().equals("yes")){
        return 1;
      }
      else {
        return 2;
      }
   }
}
class AnotherThing() {
   public void doThing(Stuff stuff){
       if(stuff.getName().equals("Tom")) {
          stuff.setName("yes");
       }
       else {
          stuff.setName("no");
       }
   }
}
class Stuff()
{
   String name;
   // name getters and setters here
}

在这种情况下,我将尝试模拟AnotherThing来测试Something

但是,我在测试的类中多次调用这个void方法。我每次调用它都需要不同的"Answer"。我的意思是,每次调用它时,我都想调用void方法来做不同的事情。

我查阅了API,但找不到解决方案。这对Mockito来说可能吗?

您需要的是一个Mockito Answer对象。这是一个包含少量功能的对象,当调用mock的方法时可以运行这些功能。查看doAnswer的Mockito文档以了解更多详细信息;但基本上你想要的是这样的东西。

  doAnswer(new Answer<Object>(){
        @Override
        public Object answer(InvocationOnMock invocation){
           Object[] arguments = invocation.getArguments();
           Stuff argument = (Stuff) arguments[0];
           if(stuff.getName().equals("Tom")) {
              stuff.setName("yes");
           }
           else {
              stuff.setName("no");
           }
           return null;
        }
     }).when(mockObject).doThing(any(Stuff.class));

有一种更简单的方法:

doNothing().doNothing().doThrow(new RuntimeException()).when(mock).someVoidMethod();

通过这种方式,对该方法的多次调用可以做不同的事情。

Mockito为您提供了一种截取连续调用的可能性。我想这正是你需要的。这里有一个链接到mockito文档中的必要部分。

你可以这样写:

Mockito.when(mockAnotherThing.doThing(stuff)).thenReturn("yes").thenReturn("no");

在此之后,mockito在第一次调用时将返回"yes",在第二次调用时返回"no"。

顺便说一句,我认为你需要像这样修改你的示例代码(在其他情况下,它不会起作用):

class AnotherThing() {
   public String doThing(Stuff stuff){
       if(stuff.getName().equals("Tom")) {
         return "yes";
       }
       else {
          return "no";
       }
   }
}

您不能使用equals,因为返回类型为void,或者将doThing()的返回类型更改为String,然后像这样模拟

 Anotherthing anotherthing = mock(Anotherthing.class)
 when(anotherThing.doThing(isA(Stuff.class))).thenReturn("yes").thenReturn("no");

您可能需要多次对此进行模拟,否则将在连续2次调用后返回最后一个存根值("no");

为什么需要不同的Answer?你可以使用同一个:

doAnswer(new Answer<Object>(){
    private int call;
    @Override
    public Object answer(InvocationOnMock invocation){
        ...
        call = call + 1;
        if (call % 2 == 0) {
        //do something
        } else {
        //another behavior 
        }
    }
 }).when(mockObject).doThing(any(Stuff.class));

相关内容

  • 没有找到相关文章