利用Mockito的捕获功能改善测试

单元测试强制要求在隔离测试单元。 为了实现这一点,通常的共识是使用DI以分离的方式设计我们的类。 在这种范式中,无论是否使用框架,使用编译时还是运行时编译,对象实例化都是专用工厂的责任。 特别是,这意味着new关键字应仅在这些工厂中使用。

但是,有时不适合拥有专门的工厂。 将窄范围的实例注入到更大范围的实例时,就是这种情况。 我最近偶然发现的一个用例是事件总线,它是这样的代码:

publicclassSample{
    privateEventBuseventBus;

    publicSample(EventBuseventBus){
        this.eventBus=eventBus;
    }

    publicvoiddone(){
        Resultresult=computeResult()
        eventBus.post(newDoneEvent(result));
    }

    privateResultcomputeResult(){
        ...
    }
}

使用运行时DI框架(例如Spring框架),并且如果DoneEvent没有参数,则可以将其更改为查找方法模式。

publicvoiddone(){
    eventBus.post(getDoneEvent());
}

publicabstractDoneEventgetDoneEvent();

不幸的是,这种论点只是阻止我们使用这个漂亮的把戏。 无论如何,它不能通过运行时注入来完成。 但是,这并不意味着不应该测试done()方法。 问题不仅在于如何断言在调用该方法时是否在总线上发布了新的DoneEvent ,而且还检查了包装的结果。

经验丰富的软件工程师可能知道Mockito.any(Class<?>)方法。 可以这样使用:

publicvoiddoneShouldPostDoneEvent(){
    EventBuseventBus=Mockito.mock(EventBus.class);
    Samplesample=newSample(eventBus);
    sample.done();
    Mockito.verify(eventBus).post(Mockito.any(DoneEvent.class));
}

在这种情况下,我们确保将正确类型的事件发布到队列中,但是我们不确定结果是什么。 而且,如果无法确定结果,则对代码的置信度会降低。 Mockito进行营救。 Mockito提供捕获,就像参数的占位符一样。 上面的代码可以这样更改:

publicvoiddoneShouldPostDoneEventWithExpectedResult(){
    ArgumentCaptor<DoneEvent>captor=ArgumentCaptor.forClass(DoneEvent.class); (1)
    EventBuseventBus=Mockito.mock(EventBus.class);
    Samplesample=newSample(eventBus);
    sample.done();
    Mockito.verify(eventBus).post(captor.capture()); (2)
    DoneEventevent=captor.getCapture(); (3)
    assertThat(event.getResult(),is(expectedResult)); (4)
}
  1. 我们创建一个新的ArgumentCaptor
  2. 我们用captor.capture()替换any()用法,技巧就完成了。
  3. 然后,结果由Mockito捕获,并可以通过captor.getCapture()
  4. 使用Hamcrest,确保结果是预期的结果。

翻译自: https://blog.frankel.ch/improve-your-tests-with-mockitos-capture/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值