敲碎时间的人的个人专栏
上一篇

Mockito ArgumentCaptor @Captor

广告
选中文字可对指定文章内容进行评论啦,→和←可快速切换按钮,绿色背景文字可以点击查看评论额。
大纲

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()方法来获取值;

这些基础知识挺简答的,但是组合起来就会发挥巨大的作用。

 

版权声明:著作权归作者所有。