jahmaican
jahmaican

Reputation: 162

How to use two different argument captors in one test method?

I have a problem using captors to test two separate calls of the same method, but with different argument type.

I provided a code sample of what I'm trying to do here - basically I want to verify if certain method was called twice but with different type arguments using two separate captors, and then call some assertions on captured objects.

public class Foo {
}

public class Bar {
}

public interface MyClient {
  void doSomething(Object obj);
}

public class MyService {
    private MyClient client;

    void doSomething() {
        client.doSomething(new Foo());
        client.doSomething(new Bar());
    }
}

@RunWith(MockitoJUnitRunner.class)
public class MyServiceTest {

    @InjectMocks
    private MyService testObj;

    @Mock
    private MyClient myClient;

    @Captor
    private ArgumentCaptor<Foo> fooCaptor;

    @Captor
    private ArgumentCaptor<Bar> barCaptor;

    @Test
    public void testSomething() {
        testObj.doSomething();

        verify(myClient).doSomething(fooCaptor.capture());
        // ...do something with fooCaptor

        verify(myClient).doSomething(barCaptor.capture());
        // ...do something with barCaptor
    }
}

I'd expect this test would pass as is, because captors specify argument types, so shouldn't this work same as ArgumentMatchers.any(Foo.class) etc?

Currently I'm getting TooManyActualInvocations - 2 instead of 1.

How do we handle such cases? I don't like the idea of using one captor and then cast the results.

Upvotes: 3

Views: 391

Answers (1)

Janos Breuer
Janos Breuer

Reputation: 480

Try to combine the captors with the isA matcher using the and operator from the AdditionalMatchers package.

import static org.mockito.AdditionalMatchers.and;

// ...

verify(myClient).doSomething(and(isA(Foo.class), fooCaptor));
verify(myClient).doSomething(and(isA(Bar.class), barCaptor));

Upvotes: 1

Related Questions