【问题标题】:Trying to define a Mockito-stub executes the mocked method. Why?尝试定义 Mockito-stub 会执行模拟方法。为什么?
【发布时间】:2021-12-08 15:52:22
【问题描述】:

我们正在尝试定义一个 UnitTest,我们在其中模拟一个对象,为简单起见,我在此将其称为 x

...
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import org.kubek2k.springockito.annotations.SpringockitoContextLoader;
import org.kubek2k.springockito.annotations.WrapWithSpy;
...

@ContextConfiguration(
    loader = SpringockitoContextLoader.class,
    inheritLocations = true)
public class SyncServiceIntegrationTest extends AbstractIntegrationTest {

    @Autowired
    @WrapWithSpy
    private EventDrivenIssueDeliveryConfirmer x;

    ...

    @Before
    public void setUp() {
        ...
        doNothing().when(x).foobar(any(Event.class));
    }

    ...

即我们希望我们的 UT(此处未显示)稍后不在该对象 x 上调用方法 foobar

奇怪的是,我们在这个 UT 类的初始化过程中得到了一个 NPE。当传递的参数为 null 时,方法 foobar() 会抛出 NPE。

事实证明,这个带有参数null 的调用发生在setup 方法中的doNothing()... 行中,在我们的理解中,它应该只是定义模拟对象的存根。但相反,它评估any(Event.class)-表达式,显然产生null,然后在x 上调用foobar(...)-方法,这会导致NPE。

除了 NullPointerException 我们还从 Mockito 收到一条错误消息:

java.lang.NullPointerException: null
... <stack trace omitted for brevity>

org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced or misused argument matcher detected here:

-> at ch.sst.integration.SyncServiceIntegrationTest .setUp(SyncServiceIntegrationTest.java:69)

You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
... <examples omitted for brevity>

org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at ch.sst.integration.SyncServiceIntegrationTest .setUp(SyncServiceIntegrationTest.java:69)
...

为什么会这样???为什么我们的存根被认为是“未完成的”?我们在这里缺少什么?

后期补充:

这个问题似乎与类的事实有关 EventDrivenIssueDeliveryConfirmer 标有@Transactional。删除/评论让 UT 成功。但这当然不是解决方法——我们需要那个注释。 至少这提供了搜索方向的提示。 @Transactional 造成的包裹和 Mockito 完成的包裹在这里似乎互相踩了脚。

【问题讨论】:

    标签: mockito springockito


    【解决方案1】:

    我有同样的问题,但设置完全不同:kotlin、mockito,当然还有mockito-kotlin。 我对这个问题发表评论是因为将来可能有人会用 kotlin mockito 问题来回答这个问题?我确实做到了。无论如何。

    当没有在 kotlin 中将方法声明为 open 时,它会被编译为最终方法,不能被 mockito-kotlin 模拟。结果,该方法被执行,这对我来说有点奇怪,但这就是它的作用。在 https://github.com/mockito/mockito-kotlin/issues/314 下的 mockito-kotlin github 问题中提到了它

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-03
      • 1970-01-01
      相关资源
      最近更新 更多