Mockito Spy–部分模拟

时间:2020-02-23 14:40:45  来源:igfitidea点击:

我们可以使用Mockito Spy来部分模拟对象。
当我们监视对象时,除非将其存根,否则将调用真正的方法。

Mockito Spy

我们可以使用两种方法创建模仿 Spy对象。

  • Mockito.spy()方法
  • Mockito @ Spy注释

Mockito spy()方法示例

以下是使用Mockitospy()方法的简单示例。

package com.theitroad.mockito.spy;

import static org.mockito.Mockito.*;

import java.util.ArrayList;
import java.util.List;

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

public class MockitoSpyExample {

	@Test
	void test() {
		List<String> list = new ArrayList<>();
		List<String> spyOnList = spy(list);

		spyOnList.add("A");
		assertEquals(1, spyOnList.size());
		assertEquals("A", spyOnList.get(0));

		spyOnList.add("E");
		assertEquals(2, spyOnList.size());
		assertEquals("E", spyOnList.get(1));

		when(spyOnList.size()).thenReturn(10);
		assertEquals(10, spyOnList.size());
	}
}

注意,真正的实现会调用add()get()size()方法,直到它们没有被存根。
在稍后的时间,我们对size()方法进行了存根处理。
从那时起,将调用存根方法。

Mockito @Spy注释示例

这是@Spy注释的示例,我们已经将上面的测试程序转换为使用@Spy注释。

package com.theitroad.mockito.spy;

import static org.mockito.Mockito.*;

import java.util.ArrayList;
import java.util.List;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;

import static org.junit.jupiter.api.Assertions.*;

public class MockitoSpyAnnotationExample2 {

	@Spy 
	List<String> spyOnList = new ArrayList<>();
	
	@BeforeEach
	public void setup() {
		MockitoAnnotations.initMocks(this);
	}
	
	@Test
	void test() {
		spyOnList.add("A");
		assertEquals(1, spyOnList.size());
		assertEquals("A", spyOnList.get(0));
		
		spyOnList.add("E");
		assertEquals(2, spyOnList.size());
		assertEquals("E", spyOnList.get(1));

		when(spyOnList.size()).thenReturn(10);
		assertEquals(10, spyOnList.size());
	}
}

当我们不得不在多个地方重用 Spy对象时,最好使用@Spy批注。

请注意,使用其他实例创建 Spy对象不是强制性的,以下也是可接受的用法。

List<String> spyOnList = spy(List.class);

@Spy 
List<String> spyOnList1;

但是,建议提供实施。
因为在这种情况下,Mockito将尝试使用no-args构造函数实例化模拟对象。
另外,它不会实例化内部类,本地类等。
我们知道List实现类使用内部类。
因此,您将无法从测试中获得预期的结果。

Mockito Spyvs doCallRealMethod()

我们也可以在模拟对象上使用doCallRealMethod()来调用真实方法,但是,建议使用Spy创建部分模拟。
因为在Spy中,我们正在实例化一个对象,而在创建模拟对象时,Mockito会创建该对象的最小实例。
可能是在创建模拟时未初始化所需的依赖关系,从而导致错误的结果。