Mockito ArgumentCaptor, @Captor Annotation

Filed Under: Mockito

Mockito ArgumentCaptor is used to capture arguments for mocked methods. ArgumentCaptor is used with Mockito verify() methods to get the arguments passed when any method is called. This way, we can provide additional JUnit assertions for our tests.

Mockito ArgumentCaptor

We can create ArgumentCaptor instance for any class, then its capture() method is used with verify() methods.

Finally, we can get the captured arguments from getValue() and getAllValues() methods.

getValue() method can be used when we have captured a single argument. If the verified method was called multiple times then getValue() method will return the latest captured value.

If multiple arguments are captured, call getAllValues() to get the list of arguments.

Mockito ArgumentCaptor Example

Let’s say we have a class defined as:


class MathUtils {
	public int add(int x, int y) {
		return x + y;
	}

	public boolean isInteger(String s) {
		try {
			Integer.parseInt(s);
		} catch (NumberFormatException e) {
			return false;
		}
		return true;
	}
	
	public long squareLong(long l) {
		return l*l;
	}
}

We can write our test case and use ArgumentCaptor as shown below.


@Test
void test() {
	MathUtils mockMathUtils = mock(MathUtils.class);
	when(mockMathUtils.add(1, 1)).thenReturn(2);
	when(mockMathUtils.isInteger(anyString())).thenReturn(true);

	ArgumentCaptor acInteger = ArgumentCaptor.forClass(Integer.class);
	ArgumentCaptor acString = ArgumentCaptor.forClass(String.class);

	assertEquals(2, mockMathUtils.add(1, 1));
	assertTrue(mockMathUtils.isInteger("1"));
	assertTrue(mockMathUtils.isInteger("999"));

	verify(mockMathUtils).add(acInteger.capture(), acInteger.capture());
	List allValues = acInteger.getAllValues();
	assertEquals(List.of(1, 1), allValues);
	
	verify(mockMathUtils, times(2)).isInteger(acString.capture());
	List allStringValues = acString.getAllValues();
	assertEquals(List.of("1", "999"), allStringValues);
}

Mockito @Captor

We can use @Captor annotation to create argument captor at field level. So instead of initializing field level ArgumentCaptor as:


ArgumentCaptor acLong = ArgumentCaptor.forClass(Long.class);

We can use @Captor as:


@Captor ArgumentCaptor acLong;

Note that we have to call MockitoAnnotations.initMocks(this); before test methods to get it initialized by Mockito framework.

Mockito @Captor Example

Here is a simple example of @Captor annotation.


class MockitoArgumentCaptorExamples {

	@Captor ArgumentCaptor acLong;

	@Test
	void test() {
		MathUtils mockMathUtils = mock(MathUtils.class);
		when(mockMathUtils.squareLong(2L)).thenReturn(4L);
		assertEquals(4L, mockMathUtils.squareLong(2L));
		verify(mockMathUtils).squareLong(acLong.capture());
		assertTrue(2 == acLong.getValue());
	}
}
You can check out complete code and more Mockito examples from our GitHub Repository.

Comments

  1. Sebastian says:

    Nice for introduction level, but it would be really great if you could show how to work with generics and captors

  2. Viswanath Krishnamurthy says:

    Hi Pankaj,

    I am new to Mockito. I have doubts regarding Mockito. thenAnswer and about argument captor. It would be great if you could share some code snippets

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages