ArgumentCaptor is quite useful when a new object is being created within the under test method which can't be mocked / controlled by the test.
For e.g. consider below method which creates an instance of employee nad passes to the employeeTable.save
public void saveEmployee(String name, String department) { Employee employee = new Employee(UUID.randomUUID().toString(),name, department); Instant start = Instant.now(); employeeTable.save(employee); LOGGER.info("Saved - {} {} in {} millis", name, department, timeElapsed); }
The test for this method would not be complete without ArgumentCaptor.
How do we use it?
@Captor ArgumentCaptor<Employee> employeeCaptor;
Now use this captor in mockito verify method as
verify(employeeTable,times(1)).save(employeeCaptor.capture());
and then retrieve the captured value and assert against
var employee = messagesCaptor.getValue(); assertThat(history.getName()).isEqualTo("Sanjay"); assertThat(history.getDept()).isEqualTo("Engineering"); assertThat(history.getId()).isEqualTo("Engineering");
Full test here
@Test void saveEmployee(final CapturedOutput output) { employeeService.saveEmployee("Sanjay", "Engineering"); verify(employeeTable,times(1)).save(employeeCaptor.capture()); var employee = messagesCaptor.getValue(); assertThat(history.getName()).isEqualTo("Sanjay"); assertThat(history.getDept()).isEqualTo("Engineering"); assertThat(history.getId()).isEqualTo("Engineering"); assertThat(output.getOut()).contains("Saved - Sanjay Engineering in")); }