Mockito Spy示例
在Mockito的 Spy上的本程序中,我们将看到 Spy与模块不同,以及如何使用这些。
添加到ClassPath,使用Maven
将Mockito添加到项目的最快方法是使用Maven依赖项。
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-all --> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <version>1.9.5</version> </dependency>
此依赖性足够简单,不会带来任何其他或者冗余库。
请参阅此处获取最新版本的库。
使用Mockito注释
现在,要开始使用Mockito注释,我们必须事先在我们的测试类中启用它们。
有两种方式可以完成。
通过与Mockitojunitrunner注释:
@RunWith(MockitoJUnitRunner.class) public class MockitoAnnotationTest { ... }
或者,这也可以以@BEFORE注释的方法手动以编程方式完成,例如:
@Before public void init() { MockitoAnnotations.initMocks(this); }
在Mockito中的 Spy
当Mocks在Mockito中创建时,它们是从类型的类别完成的,而不是实际实例。
Spy不是这种情况。
Spy工作就像真实的实例一样,它将以与真实实例相同的方式,只是通过可以跟踪所有与方法的交互的方式来识别 Spy,如方法调用或者初始化。
让我们看看互动手段的跟踪与一个例子:
@Test public void whenCreateSpy_thenCreate() { Map spyMap = Mockito.spy(new HashMap()); spyMap.put("awesome", "theitroad"); Mockito.verify(spyMap).put("awesome", "theitroad"); assertEquals(1, spyMap.size()); }
这里:
- 使用静态 Spy(...)方法进行映射(Map) Spy
- 然后,将键值对添加到其中
- 在添加元素后,我们将其互动验证为元素添加完成
- 请注意,制作了一个真实的映射(Map)实例,我们甚至通过断言验证了它来检查其大小,实际上是1.
让我们使用@spy批注来做同样的例子:
@Spy Map<String, String> mySpyMap = new HashMap<String, String>(); @Test public void whenCreateSpy_thenCreate() { mySpyMap.put("awesome", "theitroad"); mySpyMap.put("super", "theitroad"); Mockito.verify(mySpyMap).put("awesome", "theitroad"); Mockito.verify(mySpyMap).put("super", "theitroad"); assertEquals(2, mySpyMap.size()); }
没有太大的差异。
请记住,正如我们在本程序开始的那样,我们需要使用开始时显示的方法之一激活Mockito注释。
删除 Spy
现在,让我们看看我们如何停止 Spy。
使用Stubbing,我们可以重写(overwriting)方法的行为并修改其返回值,就像我们在模拟中所做的那样。
在我们的示例中,我们将重写(overwriting)映射(Map)接口的大小()方法的行为:
@Test public void stubbedAMethod_WithSpy() { Map<String, String> spyMap = Mockito.spy(new HashMap<String, String>()); assertEquals(0, spyMap.size()); Mockito.doReturn(5).when(spyMap).size(); assertEquals(5, spyMap.size()); }
另一个例子
让我们说你有员工程序。
此员工类具有地址类的对象。
正在测试的方法:
我们将测试员工类的GetEmployEdEteTails方法。
以下是我们要测试的方法。
public String getEmployeeDetails() { return id+"_"+name+"_"+address.getAddressDetails(); }
现在在上面的方法中,让我们假设地址的GetAddressDetails()方法进行数据库调用和获取地址详细信息。
我们不想在测试中执行DB Connectin,因此我们可以简单地模拟GetEmployEdeTails()的方法和测试函数。
创建名为"employee.java"的类
public class Employee { int id; String name; Address address; public Employee(int id, String name) { super(); this.id = id; this.name = name; } public String getEmployeeDetails() { return id+"_"+name+"_"+address.getAddressDetails(); } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } }
创建另一个名为"adddress.java"的类
public class Address { int houseNo; String street; public String getAddressDetails() { //let's say this is database operation return houseNo+"_"+street; } public int getHouseNo() { return houseNo; } public void setHouseNo(int houseNo) { this.houseNo = houseNo; } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } }
创建名为"emplaceEdeTailstStest"的测试类
import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.mockito.Spy; import static org.mockito.Mockito.*; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import junit.framework.Assert; public class EmployeeDetailsTest { Employee e1; Employee e2; @Spy Address address=new Address(); @Rule public MockitoRule rule = MockitoJUnit.rule(); @Before public void setup(){ e1=new Employee(1, "John"); e1.setAddress(address); e2=new Employee(2, "Martin"); e2.setAddress(address); when(address.getAddressDetails()).thenReturn("88_HighStreet"); } @Test public void testEmployeeDetails() { String e1Details=e1.getEmployeeDetails(); Assert.assertEquals("1_John_88_HighStreet", e1Details); String e2Details=e2.getEmployeeDetails(); Assert.assertEquals("2_Martin_88_HighStreet", e2Details); } }
正如我们在这里看到的,我们使用了使用地址对象的@SPY。
when(address.getAddressDetails()).thenReturn("88_HighStreet");
上面的线模拟GetAddressDetails()方法是我们已成功使用Mockito成功避免的数据库操作。
Mock vs spy.
当Mockito创建模拟时 - 它可以从类型的类,而不是实际实例。
另一方面, Spy将是原始实例。
它仍然会以与正常实例相同的方式 - 唯一的区别是它也将被录制以跟踪与它的所有交互。
除非罚球,否则 Spy的所有方法都是真实的。