使用Mockito时,嘲笑和间谍有什么区别?

2022-08-31 06:44:43

使用Mockito间谍的用例是什么?

在我看来,每个间谍用例都可以使用callRealMethod用模拟来处理。

我可以看到的一个区别是,如果您希望大多数方法调用都是真实的,它会保存一些代码行以使用模拟与间谍。是它还是我错过了更大的图景?


答案 1

间谍和模拟之间的区别

当 Mockito 创建模拟时,它会从类型的类中执行此操作,而不是从实际实例中执行此操作。模拟只是创建类的一个基本 shell 实例,完全用于跟踪与它的交互。另一方面,间谍将包装现有实例。它仍然会以与正常实例相同的方式运行 - 唯一的区别是它也将被检测以跟踪与它的所有交互。

在下面的示例中 – 我们创建 ArrayList 类的模拟:

@Test
public void whenCreateMock_thenCreated() {
    List mockedList = Mockito.mock(ArrayList.class);

    mockedList.add("one");
    Mockito.verify(mockedList).add("one");

    assertEquals(0, mockedList.size());
}

如您所见 - 将元素添加到模拟列表中实际上并没有添加任何内容 - 它只是调用该方法,没有其他副作用。另一方面,间谍的行为会有所不同 - 它实际上会调用add方法的实际实现,并将元素添加到基础列表中:

@Test
public void whenCreateSpy_thenCreate() {
    List spyList = Mockito.spy(new ArrayList());
    spyList.add("one");
    Mockito.verify(spyList).add("one");

    assertEquals(1, spyList.size());
}

在这里,我们可以肯定地说,对象的真正内部方法被调用了,因为当你调用size()方法时,你得到的大小为1,但是这个size()方法没有被嘲笑!那么1从何而来呢?内部 real size() 方法称为 size() 未被模拟(或存根),因此我们可以说该条目已添加到真实对象中。

资料来源:http://www.baeldung.com/mockito-spy+自我笔记。


答案 2

答案在文档中

真实部分模拟(自 1.8.0 起)

最后,在邮件列表上进行许多内部辩论和讨论之后,Mockito增加了部分模拟支持。以前,我们将部分模拟视为代码气味。但是,我们发现了部分模拟的合法用例。

在1.8版本之前,spy()没有产生真正的部分模拟,这对一些用户来说是令人困惑的。阅读更多关于间谍:在这里或在javadoc for spy(Object)方法。

callRealMethod()是在 之后引入的,但是为了确保向后兼容性,spy() 当然被留在那里。spy()

否则,你是对的:间谍的所有方法都是真实的,除非被存根。除非调用,否则 mock 的所有方法都是存根的。一般来说,我更喜欢使用 ,因为它不会强迫我使用成语而不是传统的成语。callRealMethod()callRealMethod()doXxx().when()when().thenXxx()