有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Mockito ArgumentCapture无法识别多个泛型类型

我试图使用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)

为了查看发生了什么,我向verify方法添加了times(2),然后检查了参数捕获。他们都接受了第二个调用,这意味着我永远无法捕获类型为List<String>的第一个参数

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

干杯, 阿列克谢蓝


共 (4) 个答案

  1. # 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){}
    }
    
  2. # 2 楼答案

    不使用现有的ArgumentCaptor类。由于类型擦除,此信息丢失。我建议您使用一个捕获器,并在所有调用中传递参数。然后,您可以验证第一次使用List<String>调用它,第二次使用List<Boolean>调用它。当然,您可以通过验证列表的内容来实现这一点

  3. # 3 楼答案

    对我来说,我尝试两次抛出相同的错误消息

    如果您试图验证相同的按摩,则必须使用import static org.mockito.Mockito.times的“时间”方法

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

    其中,numb是相同按摩的计数