【问题标题】:Mockito verify match Optional of arrayMockito 验证匹配数组的可选
【发布时间】:2018-10-02 04:19:19
【问题描述】:

我有一个类似的方法签名

public void add(byte[] key, Optional<Byte[]> secondaryKey) { ... }

我的测试看起来像

byte[] key = "testKey".getBytes();
byte[] secondaryKey = "secondaryKey".getBytes()
//call the method that internally calls add()
Mockito.verify(mockClass).add(key, Optional.of(ArrayUtils.toObject(secondaryKey))

在这种情况下,验证总是失败,说想要的参数与实际的不同。我有一个类似的add 方法,它只是将byte[] key 作为输入参数。对该方法的测试成功。所以我认为我在这里尝试匹配Optional参数的方式有问题。

【问题讨论】:

  • byte[]Byte[] 是不同的类型。要么将参数类型设为Optional&lt;byte[]&gt;,要么将secondaryKey 转换为Byte[]
  • @AndyTurner 调用add 的方法实际上在调用add 之前将secondaryKey 转换为Byte[],与ArrayUtils.toObject(secondaryKey)。这就是我在验证器中使用它的原因
  • @AndyTurner 还尝试将所有内容更改为 Optional&lt;byte[]&gt;,但这也无济于事
  • 嗯。是否与数组缺乏有用的相等性有关?
  • 您需要使用ArgumentMatcher.eq()

标签: java unit-testing mocking mockito


【解决方案1】:

Optional 不执行deepEquals,因此考虑到您已将Byte[] 传递给Optional,相等性检查将失败。

您可以从遇到类似问题的用户那里看到此错误报告。 JDK-8075723

您可能希望利用一些 ArgumentMatchers 来比较传递给您的模拟的参数。

由于您有一个 Optional 正在传递,您可以使用 ArgumentMatchers.argThat 解开该对象,这需要您实现 ArgumentMatcher.matches 方法。

Mockito.verify(mockClass).add(ArgumentMatchers.eq(key), ArgumentMatchers.argThat(r -> {
    return r.isPresent() && Objects.deepEquals(secondaryKey, r.get())
));

编辑:

如果您希望捕获传递给模拟的参数状态并执行断言,也可以使用ArgumentCaptor

ArgumentCaptor<Optional> captor =ArgumentCaptor.forClass(Optional.class)
verify(pojo).add(eq(key), captor.capture());

Optional<byte[]> result = captor.getValue();
assertTrue(result.isPresent());
assertArrayEquals(secondaryKey, result.get());

【讨论】:

  • 是的,这行得通。只是 lambda 的第一步应该是将 r 类型转换为所需的类型 - Optional&lt;byte[]&gt; keyOpt = (Optional&lt;byte[]&gt;) r; ,然后使用 keyOpt 进行剩余断言
  • 您应该返回一个值,而不是在不匹配的情况下抛出异常。 Per the documentation(强调他们的):“如果参数不匹配,该方法应该从不断言。它应该只返回 false。”
  • 好点。当我使用电脑时,我会使用“ArgumentCaptor”更新答案。
  • 更新答案以符合 Mockito 的推荐做法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-30
相关资源
最近更新 更多