Mockito单步执行失败?

Ric*_*ene 2 java mockito

好吧,这很奇怪。Mockito,Java,在 Windows 上。

 when(mongoTemplate.findAndModify(any(Query.class), any(Update.class), any(FindAndModifyOptions.class), eq(Task.class)))
            .thenReturn(t1)
            .thenReturn(t2);
Run Code Online (Sandbox Code Playgroud)

现在,如果我在调试模式下运行它,它就可以正常工作。但是,如果我在时间上设置断点,并且单步执行,则会失败。

IntelliJ 中的错误是

org.mockito.exceptions.misusing.WrongTypeOfReturnValue: 
Task cannot be returned by toString()
toString() should return String
***
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. This exception *might* occur in wrongly written multi-threaded tests.
   Please refer to Mockito FAQ on limitations of concurrency testing. 
2. 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.
Run Code Online (Sandbox Code Playgroud)

因此,这可能是与 IntelliJ 的一些交互,希望在单步执行时“toString()”结果。也许 Mockito 需要在 OngoingStubbing 上捕获并回退到 toString ?

Jef*_*ica 5

这种行为是有意的,而且必须如此,否则toString将无法修复或无法使用。

Mockito 存根通过副作用和代理进行工作。对于像您这样的电话:

 when(mongoTemplate.findAndModify(any(Query.class), any(Update.class), any(FindAndModifyOptions.class), eq(Task.class)))
            .thenReturn(t1)
            .thenReturn(t2);
Run Code Online (Sandbox Code Playgroud)

Mockito 利用了可预测的 Java 执行顺序,它按顺序计算方法参数,然后调用方法本身,因此它会看到:

  1. any(Query.class):参数匹配器堆栈上有 1 个匹配器,返回null
  2. any(Update.class): 堆栈上有2个匹配器,返回null
  3. any(FindAndModifyOptions.class): 堆栈上有3个匹配器,返回null
  4. eq(Task.class): 堆栈上有4个匹配器,返回null
  5. findAndModify(null, null, null, null):返回findAndModify返回的内容,findAndModify现在是最近一次调用
  6. when:我们现在findAndModify用四个参数匹配器来模拟最近的调用,重置堆栈
  7. thenReturn(t1)when:在返回的存根链上添加一个操作
  8. thenReturn(t2)when:在返回的存根链上添加一个操作

如果您的 IDEtoString在步骤 5 和步骤 6 之间调用,则 Mockito 会假设您findAndModify(null, null, null, null)有意提前调用并现在尝试存根toString。由于您尝试 return t1,这意味着 Mockito 会告诉您您的存根toString()需要一个 String 但收到一个 Task 。

虽然这很烦人,但可以说比 Mockito 拒绝存根toString()或者你完全无法调用toString()模拟更不烦人。