159

在模拟框架中,您可以模拟一个对象或监视它。两者之间有什么区别,我什么时候/应该使用一个而不是另一个?

例如,查看Mockito ,我看到使用spiesmocks完成了类似的事情,但我不确定两者之间的区别。

4

7 回答 7

193

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

进行间谍活动时,您获取现有对象并仅“替换”某些方法。当您有一个庞大的类并且只想模拟某些方法(部分模拟)时,这很有用。让我引用Mockito 文档

您可以创建真实对象的间谍。当您使用 spy 时,会调用真正的方法(除非方法被存根)。

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

如有疑问,请使用模拟。

于 2012-10-10T20:22:02.437 回答
24

我将尝试在这里使用示例进行解释:

// 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 的spy 对象上,无论实际大小是多少。

简而言之,您将窥探 真实对象存根 某些方法

于 2015-10-19T19:14:04.723 回答
16

Mockito 警告说,部分模拟不是一个好的做法,您应该修改您的面向对象架构。建议使用间谍(或部分模拟)来测试遗留代码

于 2014-01-17T19:04:15.887 回答
7

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

但是在 Spy 的情况下,如果您将任何对象分配给 Spy Object 的实例变量,那么确实会影响 Spy 对象,因为 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));
    }
}
于 2019-09-03T11:27:53.787 回答
7

基于Martin FowlerMocks Aren't Stubs

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

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

存根为测试期间拨打的电话提供预设答案,通常根本不响应任何超出测试程序的内容。

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

模拟就是我们在这里讨论的内容:预先编程的对象具有期望,这些期望形成了它们期望接收的调用的规范。

于 2019-12-16T21:36:49.180 回答
3

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

当使用模拟对象时,方法在非存根时的默认行为是什么都不做。简单的意思是,如果它是一个 void 方法,那么当你调用该方法时它什么也不做,或者如果它是一个有返回值的方法,那么它可能返回 null、空或默认值。

当然,在 spy 对象中,由于它是一个真实的方法,当您没有对方法进行存根时,它会调用真实的方法行为。如果要更改和模拟该方法,则需要对它进行存根。

于 2015-10-21T07:24:24.517 回答
1

间谍有两个定义。一个是调用真实方法的地方,另一个是不调用任何功能并且只返回 null 或 null 等效值的地方,但是调用了方法,并且记录了它们的状态,通常就像方法 x 被调用了 y 次。

于 2014-11-19T19:55:21.537 回答