在模拟框架中进行模拟与间谍活动


131

模拟框架中,您可以模拟对象或对其进行监视。两者之间有什么区别?何时/应该何时使用另一种?

综观的Mockito,例如,我看到使用被做过类似的事情间谍嘲笑,但我不能确定两者之间的区别。



Answers:


157

模拟对象完全替换模拟类,返回记录的或默认值。您可以凭空创建模拟。这是单元测试中最常用的东西。

监视时,您将使用现有对象并仅“替换”某些方法。当您有一个庞大的类并且只想模拟某些方法(部分模拟)时,这很有用。让我引用Mockito文档

您可以创建真实对象的间谍。当您使用间谍时,将调用实际方法(除非对方法进行了存根)。

真正的间谍应该小心谨慎地使用,例如在处理遗留代码时。

如有疑问,请使用模拟。


1
谢谢!这使它更加清楚。因此,模拟永远不会委托给要模拟的实际对象曾经,但间谍会这样做。
Vivin Paliath 2012年

7
嘲笑没有“实际对象”-模仿是从头创建的。
Carl Manaster

4
为什么Mockito会一直警告不要使用间谍?我看到他们说赞成嘲笑,但原因尚不清楚。
马特

9
我不确定,但也许是因为它们是“ Mockito”而不是“ Spyito”:D
typoerrpr


16

我将尝试在此处使用示例进行说明:

// Difference between mocking, stubbing and spying
@Test
public void differenceBetweenMockingSpyingAndStubbing() {
    List list = new ArrayList();
    list.add("abc");
    assertEquals(1, list.size());

    List mockedList = spy(list);
    when(mockedList.size()).thenReturn(10);
    assertEquals(10, mockedList.size());
}

在这里,我们有初始的实物对象list,其中我们添加了一个元素,并且预期大小为1。

我们窥探真实对象的意义,我们可以指示要哪种方法存根。因此,我们声明了对方​​法size()进行存根- 在间谍对象上,无论实际大小如何,该对象都将返回10。

简而言之,你将间谍 实物存根 的一些方法


2

参考:http : //javapointers.com/tutorial/difference-between-spy-and-mock-in-mockito/

使用模拟对象时,方法的默认行为是不进行任何操作。简单的意思是,如果它是一个void方法,则在您调用该方法时它什么都不做,或者如果它是一个带有返回值的方法,则它可能会返回null,empty或默认值。

当然,在间谍对象中,由于它是一个真实的方法,所以当您不对方法进行存根时,它将调用真实的方法行为。如果要更改和模拟该方法,则需要对它进行存根。


2

虚拟对象会传递,但从未实际使用过。通常它们仅用于填充参数列表。

对象实际上具有有效的实现,但是通常采取一些捷径,这使它们不适合生产(内存数据库就是一个很好的例子)。

存根提供对测试期间进行的呼叫的固定答复,通常通常根本不响应为测试编程的内容。

间谍是存根,它们还会根据调用方式记录一些信息。其中一种形式可能是电子邮件服务,它记录发送了多少消息。

嘲笑是我们在这里谈论的:带有期望的预编程对象,这些对象形成了期望接收的呼叫的规范。

cks头不是马丁·福勒(Martin Fowler)


1

间谍有两个定义。一种是在其中调用实方法,另一种是在其中不调用功能,仅返回null或null等效值,但是调用了方法,并记录了它们的状态,通常就像方法x被称为y次。


0

在Mockito中,如果将任何对象分配给Mock Object的实例变量,则不会影响Mock Object。

但是对于Spy,如果将任何对象分配给Spy Object的实例变量,则确实会影响Spy Object,因为Spy就像实时对象修改一样。

作为参考示例

@RunWith(MockitoJUnitRunner.class)
public class MockSpyExampleTest {

    @Mock
    private List<String> mockList;

    @Spy
    private List<String> spyList = new ArrayList();

    @Test
    public void testMockList() {
        //by default, calling the methods of mock object will do nothing
        mockList.add("test");
        assertNull(mockList.get(0));
    }

    @Test
    public void testSpyList() {
        //spy object will call the real method when not stub
        spyList.add("test");
        assertEquals("test", spyList.get(0));
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.