【问题标题】:Using Multiple ArgumentMatchers on the same mock在同一个模拟上使用多个 ArgumentMatchers
【发布时间】:2012-12-12 19:06:16
【问题描述】:

我正在尝试在 Mock 上使用 Mockito 来做到这一点:
当使用参数 1 调用 Mock.someMethod(..) 时 --> 返回结果 1
当使用 argument2 调用 Mock.someMethod(..) 时 --> return result2
当使用 argument3 调用 Mock.someMethod(..) 时 --> return result3

    when(mock.method(Matchers.argThat(new MyMatcher1() {

        @Override
        public boolean matches(Object arg0) {
                   // comparision logic
        }
    }))).thenReturn(result1);

    when(mock.method(Matchers.argThat(new MyMatcher2() {

        @Override
        public boolean matches(Object arg0) {
                   // comparision logic
        }
    }))).thenReturn(result2);

    when(mock.method(Matchers.argThat(new MyMatcher3() {

        @Override
        public boolean matches(Object arg0) {
                   // comparision logic
        }
    }))).thenReturn(result3);

但是 Mockito 正确地存根第一个,但是在第二个上它会抛出 NullPointer 异常,因为它出于某种原因尝试使用 null agrument 运行 Matcher。我不确定它是否受支持。

如果这不是正确的方法,如何使用 Mockito 来实现?谢谢。

【问题讨论】:

  • 知道了,我总是点击那些箭头说它很有用,我认为这归功于回答的人。可能不是,我去看看。谢谢。关于链接,虽然它是一个布尔匹配器,但我创建的 ArgumentMatcher 也是一个布尔匹配器,我不认为我的与这个不同,但会尝试让你知道。
  • 链接不是很好:) 请参阅该页面上的argThatjavadoc。它确实提到了NPE

标签: java mockito


【解决方案1】:

而不是写

when(mock.method(Matchers.argThat(new MyMatcher1() {
    @Override
    public boolean matches(Object arg0) {
           // comparison logic
    }
}))).thenReturn(result1);

试试这个。

doReturn(result1).when(mock).method(Matchers.argThat(new MyMatcher1() {

    @Override
    public boolean matches(Object arg0) {
               // comparison logic
    }
}));

result2result3 也是如此。

http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html#12 对此进行了描述,但在我看来,文档并不清楚在这种情况下实际上需要这种构造。我将在这里与 Mockito 团队的其他成员讨论如何改进文档。

祝你好运。

【讨论】:

【解决方案2】:

根据经验,如果测试失败,您应该能够查明被测单元的问题所在。避免专门为一项测试编写自定义匹配器。 如果一个方法需要返回多个值,通常只需通过按测试预测的顺序返回值来简单地对方法进行存根即可。

例如

when(mock.method(any(Object.class))).thenReturn(result1, result2, result3);

这将在第一次调用时返回结果 1,在第二次调用时返回结果 2,依此类推。

这显然是不够的,但通常情况下,测试越简单越好。

【讨论】:

  • 感谢您的建议。但正如我在最初的问题中提到的那样,我的用例肯定有点不同。仅当输入为 input1 时,我才需要 result1,如果 input2 为 result2 等。它可以是任何顺序。多参数匹配器应该根据它们的设计方式工作,但感觉更像是 Mockito 中的一个错误。我能够解决这个问题,但在自定义参数匹配器中对“arg0”进行了空检查。愚蠢,但有效。也许我会和 Mockito 团队一起讨论。
【解决方案3】:

我现在可以通过在自定义 ArgumentMatcher 中进行空检查来解决这个问题。它起作用了,因为 NPE 仅在 Mockito 调用 when() 语句时才在启动期间。此时它甚至不应该调用 ArgumentMatcher.matches() !感觉就像 Mockito 中的一个错误。

【讨论】:

  • 与 EasyMock 不同,Mockito 在“设置”和“重播”模式之间没有区别。因此,当您的代码显示when(mock.foo(123)).thenReturn(456); 时,它首先评估mock.foo(123),就好像您是从被测系统中调用它一样——这意味着它会检查其参数以找出在遇到when 之前要返回的内容。有关避免此问题的替代语法,请参阅 David 的出色答案。请记住,Matchers 永远不应该抛出异常,即使是 NPE;考虑使用 Hamcrest 的 TypeSafeMatcher 来为自己节省检查和强制转换。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多