Skip to content

Enhancement: ArgumentCaptor.captureIf(ArgumentMatcher) #358

@ChristianSchwarz

Description

@ChristianSchwarz

Assume we have the following test.

 @Mock
 private Consumer<Collection<?>> consumer;

 @Test
 public void test() throws Exception {

    consumer.accept(new HashSet<>());
    consumer.accept(new ArrayList<>());

    ArgumentCaptor<ArrayList<?>> captor = ArgumentCaptor.forClass(ArrayList.class);
    verify(consumer).accept(captor.capture());
 }

The test fails with:

org.mockito.exceptions.verification.TooManyActualInvocations:
consumer.accept(<Capturing argument>);
Wanted 1 time:
-> at foo.TestClass.testName(TestClass.java:64)
But was 2 times. Undesired invocation:
-> at agh.TestClass.testName(TestClass.java:61)

    at foo.TestClass.test(TestClass.java:64)
    [..]

The test fails because the ArgumentCaptor stores every type, because the type information is erased a runtime. How can we capture the type that is specified in the captor, in this case ArrayList? It is possible to implement an Answerthat stores the argument, and use
Matchers.isA(ArrayList.class)but thats ugly->

doAnswer(captureArg1).when(consumer).accept(isA(ArrayList.class));

Maybe it is a good idea to create a pull req and extend the ArgumentCaptor API by adding a method like <T> T captureIf(ArgumentMatcher<? extends T>)?

Then we could write:
verify(consumer).accept(captor.captureIf(isA(ArrayList.class)));

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions