在使用Mockito时,模拟和间谍有什么区别?

Mockito间谍的用法是什么?

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

我可以看到的一个区别是,如果你想大部分的方法调用是真实的,它会节省一些代码来使用模拟与间谍。 这是我还是错过了更大的图片?

答案在文档中 :

真正的部分嘲笑(自1.8.0)

最后,在邮件列表上进行了许多内部辩论和讨论后,部分模拟支持被添加到Mockito。 以前我们把部分模拟视为代码味道。 但是,我们发现了部分模拟的合法用例 – 更多阅读: 这里

在发布之前1.8版本的spy()并没有产生真正的部分嘲讽,这让一些用户感到困惑。

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

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

间谍和模拟之间的区别

当Mockito创build一个模拟 – 它是从一个类的类,而不是从一个实际的实例。 这个模拟只是创build一个类的简单的shell实例,完全用来跟踪与它的交互。 另一方面,间谍将包装现有的实例。 它仍然会像普通实例一样运行 – 唯一的区别是它也将被用来跟踪与它的所有交互。

在下面的例子中 – 我们创build了一个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从哪里来? 内部真正的size()方法被调用,因为size()没有被模拟(或者stubbed),因此我们可以说这个入口被添加到了真实的对象中。

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

如果有8个方法的对象,你有一个testing,你想调用7个真正的方法,并存根一个方法,你有两个select:

  1. 使用模拟你将不得不通过调用7 callRealMethod和存根一个方法来设置它
  2. 使用spy你必须通过一种方法来设置它

关于doCallRealMethod的官方文档build议使用间谍来进行部分doCallRealMethod

另请参阅javadoc间谍(对象)了解更多关于部分嘲笑。 Mockito.spy()是创build部分模拟的推荐方法。 原因是它保证真正的方法被称为正确构造的对象,因为你负责构造传递给spy()方法的对象。