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的所有方法都是真实的。

