Mockito ArgumentCaptor完全指南:掌握@Captor注解的使用方法与实例

Mockito的ArgumentCaptor(参数捕获器)用于捕获模拟方法中的参数。ArgumentCaptor与Mockito的verify()方法结合使用,可以获取调用任何方法时传递的参数值。这样,我们能够在测试中添加额外的JUnit断言。

模拟参数捕获器

我们可以为任何类创建ArgumentCaptor实例,然后使用其capture()方法与verify()方法一起使用。最后,我们可以通过getValue()和getAllValues()方法获取捕获的参数。当只捕获了一个参数时,可以使用getValue()方法。如果被验证的方法被多次调用,getValue()方法将返回最新捕获的值。如果捕获了多个参数,则应调用getAllValues()方法获取参数列表。

Mockito参数捕获器示例

假设我们有一个定义如下的类:

class MathUtils {
	public int add(int x, int y) {
		return x + y;
	}

	public boolean isInteger(String s) {
		try {
			Integer.parseInt(s);
		} catch (NumberFormatException e) {
			return false;
		}
		return true;
	}
	
	public long squareLong(long l) {
		return l*l;
	}
}

我们可以根据以下示例编写测试用例,并使用ArgumentCaptor。

@Test
void test() {
	MathUtils mockMathUtils = mock(MathUtils.class);
	when(mockMathUtils.add(1, 1)).thenReturn(2);
	when(mockMathUtils.isInteger(anyString())).thenReturn(true);

	ArgumentCaptor acInteger = ArgumentCaptor.forClass(Integer.class);
	ArgumentCaptor acString = ArgumentCaptor.forClass(String.class);

	assertEquals(2, mockMathUtils.add(1, 1));
	assertTrue(mockMathUtils.isInteger("1"));
	assertTrue(mockMathUtils.isInteger("999"));

	verify(mockMathUtils).add(acInteger.capture(), acInteger.capture());
	List allValues = acInteger.getAllValues();
	assertEquals(List.of(1, 1), allValues);
	
	verify(mockMathUtils, times(2)).isInteger(acString.capture());
	List allStringValues = acString.getAllValues();
	assertEquals(List.of("1", "999"), allStringValues);
}

使用 @Captor 注解

我们可以使用@Captor注解在字段级别创建参数捕获器。因此,不需要像之前那样手动初始化字段级别的ArgumentCaptor:

ArgumentCaptor acLong = ArgumentCaptor.forClass(Long.class);

我们可以将 @Captor 用作:

@Captor ArgumentCaptor acLong;

请注意,在测试方法执行之前,我们必须调用MockitoAnnotations.initMocks(this)来通过Mockito框架进行初始化。

Mockito的@Captor使用示例

下面是一个@Captor注解的简单示例。

class MockitoArgumentCaptorExamples {

	@Captor ArgumentCaptor acLong;

	@Test
	void test() {
		MathUtils mockMathUtils = mock(MathUtils.class);
		when(mockMathUtils.squareLong(2L)).thenReturn(4L);
		assertEquals(4L, mockMathUtils.squareLong(2L));
		verify(mockMathUtils).squareLong(acLong.capture());
		assertTrue(2 == acLong.getValue());
	}
}

你可以从我们的GitHub存储库中查看完整的代码和更多的Mockito示例。

bannerAds