Tutorial

Mockito ArgumentCaptor, @Captor Annotation

Published on August 3, 2022
Default avatar

By Pankaj

Mockito ArgumentCaptor, @Captor Annotation

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

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.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors
Default avatar
Pankaj

author

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
JournalDev
DigitalOcean Employee
DigitalOcean Employee badge
June 2, 2021

The article was very informative and helped me solve an issue I was having. Thank you.

- John Yeary

    JournalDev
    DigitalOcean Employee
    DigitalOcean Employee badge
    April 12, 2021

    this example uses Mockito to test MathUtils, and proceeds to mock the very SUT that is being tested - when would anyone ever do that? A better way to demonstrate the usefulness of a captor would be to provide a non-contrived example of testing a SUT and mocking its dependencies with captors.

    - JH

      JournalDev
      DigitalOcean Employee
      DigitalOcean Employee badge
      October 14, 2020

      for me it only works like this: @ExtendWith(MockitoExtension.class) public class MathUtilsTest { @Captor ArgumentCaptor longArgumentCaptor; @Test void testAnnotate() { MathUtils mockMathUtils = mock(MathUtils.class); when(mockMathUtils.squareLong(2L)).thenReturn(4L); assertEquals(4L, mockMathUtils.squareLong(2L)); verify(mockMathUtils).squareLong( longArgumentCaptor.capture()); assertTrue(2 == longArgumentCaptor.getValue()); } }

      - HF

        JournalDev
        DigitalOcean Employee
        DigitalOcean Employee badge
        September 13, 2020

        It is worthwhile to complete things that are worth starting and ending. Smart people always do things from beginning to end.

        - Yeates.Melody

          JournalDev
          DigitalOcean Employee
          DigitalOcean Employee badge
          August 6, 2020

          For any of those who is got argument mismatch with @Captor usage; You should define argument type when declaring variable with captor. If you want to capture string; @Captor ArgumentCaptor stringArgumentCaptor; Or your specific class; @Captor Argument personArgumentCaptor; yw :)

          - Hakan

            JournalDev
            DigitalOcean Employee
            DigitalOcean Employee badge
            March 15, 2020

            Hi Pankag, I am new to mockito,I come across ‘with’ block/keyword in mockito, I am not able to understand the use of ‘with’ in mockito, so I would like to request you to please let me know the use and meaning of ‘with’’ in mockito. Ex. with(viewModel) { someMthodCall() } verify(repository).times(1).someMethodCall(capture(argument)) assertEqual(“”,“”)

            - Rohit

              JournalDev
              DigitalOcean Employee
              DigitalOcean Employee badge
              March 15, 2020

              what is ‘with’ block in mockito ?

              - Rohit

                JournalDev
                DigitalOcean Employee
                DigitalOcean Employee badge
                March 20, 2019

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

                - Sebastian

                  JournalDev
                  DigitalOcean Employee
                  DigitalOcean Employee badge
                  March 18, 2019

                  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

                  - Viswanath Krishnamurthy

                    Try DigitalOcean for free

                    Click below to sign up and get $200 of credit to try our products over 60 days!

                    Sign up

                    Join the Tech Talk
                    Success! Thank you! Please check your email for further details.

                    Please complete your information!

                    Get our biweekly newsletter

                    Sign up for Infrastructure as a Newsletter.

                    Hollie's Hub for Good

                    Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

                    Become a contributor

                    Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

                    Welcome to the developer cloud

                    DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

                    Learn more
                    DigitalOcean Cloud Control Panel