莫基托 - @Spy vs @Mock
2022-08-31 07:27:04
Mockito - 我知道间谍在对象上调用真实方法,而模拟在双对象上调用方法。此外,除非有代码异味,否则应避免间谍。但是,间谍是如何工作的,我什么时候应该实际使用它们?它们与模拟有何不同?
Mockito - 我知道间谍在对象上调用真实方法,而模拟在双对象上调用方法。此外,除非有代码异味,否则应避免间谍。但是,间谍是如何工作的,我什么时候应该实际使用它们?它们与模拟有何不同?
从技术上讲,“模拟”和“间谍”都是一种特殊的“测试替身”。
不幸的是,Mockito使这种区别变得奇怪。
mockito 中的 mock 是其他 mocking 框架中的普通 mock(允许您存根调用;即,从方法调用中返回特定值)。
mockito中的间谍是其他模拟框架中的部分模拟(部分对象将被模拟,部分将使用真实方法调用)。
两者都可用于模拟方法或字段。不同之处在于,在模拟中,您正在创建一个完整的模拟或假对象,而在间谍中,有真实对象,您只是监视或存根它的特定方法。
当然,在间谍对象中,由于它是一个真正的方法,因此当您不存根该方法时,它将调用真正的方法行为。如果要更改和模拟该方法,则需要对其进行存根。
请考虑以下示例作为比较。
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class MockSpy {
@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");
Mockito.verify(mockList).add("test");
assertEquals(0, mockList.size());
assertNull(mockList.get(0));
}
@Test
public void testSpyList() {
//spy object will call the real method when not stub
spyList.add("test");
Mockito.verify(spyList).add("test");
assertEquals(1, spyList.size());
assertEquals("test", spyList.get(0));
}
@Test
public void testMockWithStub() {
//try stubbing a method
String expected = "Mock 100";
when(mockList.get(100)).thenReturn(expected);
assertEquals(expected, mockList.get(100));
}
@Test
public void testSpyWithStub() {
//stubbing a spy method will result the same as the mock object
String expected = "Spy 100";
//take note of using doReturn instead of when
doReturn(expected).when(spyList).get(100);
assertEquals(expected, spyList.get(100));
}
}
当你使用模拟或间谍时?如果您想安全并避免调用外部服务,并且只想测试单元内部的逻辑,请使用mock。如果你想调用外部服务并执行真正依赖关系的调用,或者简单地说,你想按原样运行程序,只是存根特定的方法,那么使用spy。这就是间谍和嘲笑之间的区别。