Mockito ArgumentCaptor 用于捕获模拟方法的参数。ArgumentCaptor 与 Mockito verify() 方法一起使用,以在调用任何方法时获取传递的参数。这样,我们可以为我们的测试提供额外的 JUnit 断言。
Mockito ArgumentCaptor
我们可以为任何类创建 ArgumentCaptor 实例,然后它的 capture() 方法与 verify() 方法一起使用。最后,我们可以从 getValue() 和 getAllValues() 方法中获取捕获的参数。当我们捕获单个参数时,可以使用 getValue() 方法。如果多次调用验证的方法,则 getValue() 方法将返回最新捕获的值。如果捕获了多个参数,则调用 getAllValues() 以获取参数列表。
举个例子:
public 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;
}
}
测试代码如下:
@RunWith(MockitoJUnitRunner.class)
public class MathUtilsTest {
@Test
public void test() {
MathUtils mockMathUtils = mock(MathUtils.class);
when(mockMathUtils.add(1, 1)).thenReturn(2);
when(mockMathUtils.isInteger(anyString())).thenReturn(true);
ArgumentCaptor<Integer> acInteger = ArgumentCaptor.forClass(Integer.class);
ArgumentCaptor<String> 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);
}
}
这里说明一下:在第一个加法当中,我们首先通过 verify(mockMathUtils).add(acInteger.capture(), acInteger.capture());
来捕获参数,这里显然捕获到的是1和1,然后将所有的值取出来进行比较;同理,在第二个验证方法是不是整数中,分别用不同的参数调用了两次,然后将其值捕获后进行比较。
Mockito @Captor
我们可以使用@Captor 注释在字段级别创建参数捕获器。因此,不要将字段级别 ArgumentCaptor 初始化为:
ArgumentCaptor<Long> acLong = ArgumentCaptor.forClass(Long.class);
我们可以将@Captor 用作:
@Captor
ArgumentCaptor<Long> acLong;
请注意,我们必须调用 MockitoAnnotations.initMocks(this);在测试方法之前让它被 Mockito 框架初始化。
@Captor
ArgumentCaptor<Long> acLong;
@Test
public void testAnnotation() {
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());
}
在这种情况下,我只捕获了单个的值,所以直接使用了getValue()方法来获取值;
这些基础知识挺简答的,但是组合起来就会发挥巨大的作用。