question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Enhancement: ArgumentCaptor.captureIf(ArgumentMatcher)

See original GitHub issue

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)));

Issue Analytics

  • State:open
  • Created 8 years ago
  • Reactions:2
  • Comments:14 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
ChristianSchwarzcommented, Mar 18, 2016

@terebesirobert thank you for being open minded and considering my “hints”, good style of cooperation !

1reaction
ChristianSchwarzcommented, Mar 17, 2016

I have some questions about the user experience/expectation of the captureIf(..) API.

Use Case 1:

ArgumentCaptor<Collection> captor = ...
Consumer<Collection> consumer = mock(Consumer.class)

consumer.consume(new ArrayList());
consumer.consume(new HashSet());

verify(consumer).consume(captor.captureIf(instanceOf(List.class)));
verify(consumer).consume(captor.captureIf(instanceOf(Set.class)));

List<Collection> values = captor.getValues(); 

What should be the content of values here?

  • I would expect values contains an ArrayListand a HashSetinstance.

Use Case 2:

ArgumentCaptor<Number> captor = ...
Consumer<Number> consumer = mock(Consumer.class)

consumer.consume(1);
consumer.consume(-2);

verify(consumer).consume(captor.captureIf(gt(0))); //greater than 2
verify(consumer).consume(captor.capture());

List<Collection> values = captor.getValues(); 

What should be the content of values here?

  • I would expect valuescontains 1 and -2 cause both arguments will be covered by capture() (equivalent to captureIf(any())) and 1 will be covered by gt(0)

Use Case 3:

ArgumentCaptor<Number> captor = ...
Consumer<Number> consumer = mock(Consumer.class)

consumer.consume(1);
consumer.consume(null);

verify(consumer).consume(captor.captureIf(isNotNull()));
verify(consumer).consume(captor.captureIf(isNull()));

List<Collection> values = captor.getValues(); 

What should be the content of values here?

  • I would expect valuescontains 1 and null cause the arguments matchers a combined with or (isNull or isNotNull)
Read more comments on GitHub >

github_iconTop Results From Across the Web

Using Mockito ArgumentCaptor - Baeldung
ArgumentCaptor allows us to capture an argument passed to a method to inspect it. This is especially useful when we can't access the...
Read more >
Mockito ArgumentCaptor, @Captor Annotation - DigitalOcean
Mockito ArgumentCaptor is used to capture arguments for mocked ... We can use @Captor annotation to create argument captor at field level.
Read more >
Can I mix Argument Captor and a regular matcher?
In this case do I need to write a captor for each argument in spite of the fact I need to capture only...
Read more >
Mockito 2 tutorial for beginners: Argument Matchers - YouTube
In this video tutorial of Mockito for beginners you will learn the how to implement argument matchers.The following topics are covered:1) ...
Read more >
ArgumentCaptor (Mockito 2.28.2 API) - javadoc.io
custom argument matcher is not likely to be reused; you just need it to assert on argument values to complete verification. Custom argument...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found