4

我正在使用 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 甚至可以做到这一点吗?

4

5 回答 5

5

你需要的是一个 MockitoAnswer对象。这是一个包含少量功能的对象,您可以在调用模拟方法时运行这些功能。查看 Mockito 文档以doAnswer获取更多详细信息;但基本上你想要的是这样的。

  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));
于 2012-07-24T08:47:48.940 回答
3

有一个更简单的方法

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

这样,对方法的多次调用可以做不同的事情。

于 2015-04-02T16:09:47.493 回答
2

Mockito 让您可以存根连续调用。我认为这就是你所需要的。这是mockito 文档中必要部分的链接。

你可以这样写:

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

在第一次调用期间这个模拟之后将返回“是”,然后在第二次 - “否”。

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

class AnotherThing() {
   public String doThing(Stuff stuff){
       if(stuff.getName().equals("Tom")) {
         return "yes";
       }
       else {
          return "no";
       }
   }
}
于 2012-07-24T06:09:30.207 回答
0

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

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

你可能想多次模拟这个,否则在 2 次连续调用后最后一个存根值(“否”被返回);

于 2012-07-24T06:25:08.457 回答
0

为什么需要不同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));
于 2012-07-24T09:40:15.020 回答