Mockito Spy示例

时间:2020-02-23 14:41:35  来源:igfitidea点击:

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