【发布时间】:2020-05-07 15:45:02
【问题描述】:
我有一个包含以下三个方法的类:
void add(Service... objs)
void add(Collection<Service> objs)
void add(Stream<Service> objs)
如您所料,这些都支持添加零个或多个对象,这些对象可以单独指定,也可以作为数组、集合或流的一部分指定。前两个变体从它们的参数创建一个流,并将它们传递给实际执行添加的第三个变体。
在测试使用此类的对象时,我使用 Spring 的 @MockBean 注解创建了一个 Mockito 模拟对象来表示此类的一个实例。我可以在调试器中看到被测对象包含模拟对象,并且我期望的调用(带有服务类型的单个参数)正在发送给模拟对象。因为应该调用的方法是第一个变体(可变参数),而且我知道可变参数有点棘手,所以我编写了测试代码以检查是否使用正确的参数调用了模拟,如下所示:
ArgumentCaptor<Service> captor = ArgumentCaptor.forClass(Service.class);
verify(theMock).add(captor.capture());
assertThat(captor.getAllValues()).containsExactly(expectedService);
但是,当我运行此代码时,断言失败,因为 captor.getAllValues() 返回的列表不包含服务,而是包含流:失败消息显示:
java.lang.AssertionError:
Expecting:
<[java.util.stream.ReferencePipeline$Head@2cfe272f]>
to contain exactly (and in same order):
<[com.xxx.data.Service@37c5]>
but some elements were not found:
<[com.xxx.data.Service@37c5]>
and others were not expected:
<[java.util.stream.ReferencePipeline$Head@2cfe272f]>
当我在调试器中运行代码时,我可以看到被测对象对add(Service...)的调用调用了真正的实现;这会调用add(Stream<Service>),而正是该调用被模拟截获。这解释了为什么我看到失败,但我不明白为什么模拟无法拦截原始调用,或者我可以做些什么来让它这样做。
【问题讨论】:
标签: java spring unit-testing mockito