Mockito ArgumentCaptor不识别多种泛型类型

时间:2014-08-06 14:04:26

标签: java unit-testing junit mockito

我试图使用Mockito的ArgumentCapture来检索使用的泛型参数,但是在我的方法中使用了相同的基类型,但使用了两次不同的泛型参数。

为了简化示例,我编写了一个与我的代码不同的测试,但遇到了同样的问题:

    @Captor private ArgumentCaptor<ArrayList<String>> stringl;
    @Captor private ArgumentCaptor<ArrayList<Boolean>> booleanl;

    @Before
    public void setup()  
    {
        MockitoAnnotations.initMocks(this);      
    } //setup

    @Test
    public void test()
    {
        Foo foo = mock(Foo.class);

        List<String> stringList = new ArrayList<String>();
        List<Boolean> booleanList = new ArrayList<Boolean>();

        foo.doSomething(stringList);
        foo.doSomething(booleanList);

        verify(foo).doSomething(stringl.capture());
        verify(foo).doSomething(booleanl.capture());
    } //test

    private static class Foo
    {
        public <T> void doSomething(List<T> list){}
    }

执行测试会产生以下错误:

org.mockito.exceptions.verification.TooManyActualInvocations: 
foo.doSomething(<Capturing argument>);
Wanted 1 time:
-> at test(Test.java:19)
But was 2 times. Undesired invocation:
-> at test(Test.java:21)

为了查看发生了什么,我在验证方法中添加了times(2),然后检查了参数捕获。两者都选择了第二次调用,这意味着我永远无法捕获List<String>类型的第一个参数。

有没有办法让ArgumentCapture识别相同基本类型的不同泛型类型,即区分List<Boolean>List<String>

干杯, 阿列克谢蓝色

4 个答案:

答案 0 :(得分:2)

替代方案是注入ArgumentCaptor

@Captor
private ArgumentCaptor<List<Person>> argumentCaptor;

http://blog.jdriven.com/2012/10/mockito-using-argumentcaptor-for-generic-typed-collections/

答案 1 :(得分:1)

不使用现有的ArgumentCaptor课程。由于类型擦除,此信息将丢失。我建议你使用一个captor并在所有调用中传递参数。然后,您可以验证它是第一次使用List<String>进行调用,第二次使用List<Boolean>进行调用。当然,您可以通过验证列表的内容来完成此操作。

答案 2 :(得分:1)

我对此进行的更改是:

@Captor private ArgumentCaptor<ArrayList<?>> aList;

@Before
public void setup()  
{
    MockitoAnnotations.initMocks(this);      
} //setup

@Test
public void test()
{
    Foo foo = mock(Foo.class);

    String testString = "Hello Test";
    Boolean testBoolean = true;

    List<String> stringList = new ArrayList<String>();
    stringList.add(testString);

    List<Boolean> booleanList = new ArrayList<Boolean>();
    booleanList = testBoolean;

    foo.doSomething(stringList);
    foo.doSomething(booleanList);

    //verify to capture and assertion that it happened twice
    verify(foo, times(2)).doSomething(aList.capture());

    //Get all captured values from the verified invocation
    List<ArrayList<?>> args aList.getAllValues();

    //verify first list, should be String
    assertEquals("TestString assertion wrong", testString, args.get(0).get(0));

    //verify second list, should be Boolean
    assertEquals("TestBoolean assertion wrong", testBoolean, args.get(1).get(0));
} //test

private static class Foo
{
    public <T> void doSomething(List<T> list){}
}

答案 3 :(得分:-3)

对我来说,我试图抛出相同的错误按摩两次。

如果您正在尝试验证相同的按摩,那么您必须使用import static org.mockito.Mockito.times的“时间”方法;

verify(anyFakeObject,times(num)).method(parmeter);

麻木是同样按摩的计数。