错误:a * different * void方法无法使用返回值进行存根

时间:2016-02-12 23:20:07

标签: java mockito

当存根ClassOne.methodOne时,我收到以下关于使用返回值对void方法进行存根的错误消息,即使ClassOne.methodOne不为空。该错误似乎与ClassTwo.methodTwo有关,即使我正在查找ClassOne.methodOne

org.mockito.exceptions.base.MockitoException: 
`'methodTwo'` is a *void method* and it *cannot* be stubbed with a *return value*!
Voids are usually stubbed with Throwables:
    doThrow(exception).when(mock).someVoidMethod();
***

If you're unsure why you're getting above error read on.
Due to the nature of the syntax above problem might occur because:
1. The method you are trying to stub is *overloaded*. Make sure you are calling
   the right overloaded version.
2. Somewhere in your test you are stubbing *final methods*. Sorry, Mockito does not
   verify/stub final methods.
3. A spy is stubbed using `when(spy.foo()).then()` syntax. It is safer to stub
   spies with `doReturn|Throw()` family of methods. More in javadocs for
   Mockito.spy() method.

我的代码:

public class ClassOne {
  private ClassTwo classTwo;

  public boolean methodOne() {
    classTwo.methodTwo();
    return true;
  }
}

我的测试:

when(classOne.methodOne("some string")).thenReturn(true);

为什么会发生这种情况,我该如何解决?

1 个答案:

答案 0 :(得分:3)

当您尝试存根Mockito无法覆盖的方法时,可能会发生这种情况。 when的语法工作方式,Mockito识别它可以检测到的最新调用< / em>作为对stub的方法调用。如果Mockito无法检测到方法调用你是存根,但可以检测到在存根方法的实际实现中发生的模拟调用,那么它可能会将该调用误认为是存根调用。因此,它认为你使用返回值来存在void方法ClassTwo.methodTwo,并抛出异常。

/* 1 */  when(classOne.methodOne("some string")).thenReturn(true);
/* 2 */  when(              false              ).thenReturn(true);
/* 3 */  (    internal mockito stub object     ).thenReturn(true);

通常情况下,Mockito会调用classOne.methodOne,这是模拟上的一个未设置方法。 Mockito的默认实现检测到调用,将调用记录为最后收到的调用,并返回false。然后,在上面的步骤2中,Mockito看到对when的调用,将最后一次调用标记为存根,并准备调用thenVerb,这将在步骤3中进行。但是,在这种情况下,在第一步中,Mockito没有覆盖methodOne,因此它无法检测到呼叫或记录调用。它实际上会调用classOne.methodOne,如果与模拟有任何交互,则会记录这些内容,就好像它们在when调用之上的测试中一样。第2步和以前一样,除了Mockito标记了对存根的错误调用,因此第3步看到了thenReturn对void方法的调用。

如果使用Matchers,这可能会更麻烦,因为如果internal matcher stack上的匹配器数量错误,那么即使测试中的存根调用似乎使用了匹配器,也可能会出现InvalidUseOfMatchersException正确。

当Mockito无法覆盖您正在存根的方法时,会出现此问题。您需要检查以下内容是否正确:

  • 该课程应为非final,且不应为non-public parents
  • 该方法应为非static和非final
  • 该实例应该是Mockito模拟。请注意,如果它是使用@InjectMocks创建的,那么它是一个真正的实现,而不是模拟; read more here
  • 如异常中所述,当盯住间谍use doReturn/doAnswer/doThrow syntax时,因为否则你将在调用when内调用间谍的实际方法。