🕐 Reading time: 2 minutes
No WebFlux this time: a simple pill for anyone who writes (or should write) tests in Java. So, yes, pretty much everyone!
Have you ever wanted to check what actually gets passed to a mocked method? Not whether it was called – verify() does that – but with which object, with which data?
📑 The example
In the snippet below I used ArgumentCaptor (from the Mockito lib) to intercept the object passed to a save(...) method on a mock. It's a handy tool for those cases where you want to inspect the real content of the objects flowing through, well, your mocked methods.
@SuppressWarnings("squid:S3577")
class SampleTest016 {
@Getter
@AllArgsConstructor
private static class Car {
private String model;
private int year;
}
private interface CarRepository {
void save(final Car car);
}
@AllArgsConstructor
private static class CarService {
private CarRepository repository;
public void addNewModel(final String model, final int year) {
repository.save(new Car(model, year));
}
}
@Test
void test_addNewModel_savesCarWithCorrectData() {
final CarRepository carRepository = mock(CarRepository.class);
final CarService carService = new CarService(carRepository);
//build a captor to catch Car instances passed to the mock
final ArgumentCaptor<Car> captor = ArgumentCaptor.forClass(Car.class);
carService.addNewModel("Porsche 356A", 1956);
verify(carRepository, times(1)).save(captor.capture()); //capture the argument from the save() method
final Car savedCar = captor.getValue(); //fetch the captured Car object
assertEquals(1956, savedCar.getYear());
assertEquals("Porsche 356A", savedCar.getModel());
}
}
🔍 How does it work?
- first you define an
ArgumentCaptor<T>, passing between the< >the type to intercept (e.g.ArgumentCaptor<Car>). If the mocked method has several parameters, you can create moreArgumentCaptors, one for each type capture()intercepts the argument passed to a mocked methodgetValue()returns that object so you can check its values in your assertions
📌 Why and when to use it?
Personally I don't see it used often, but it's a great tool when you want to verify the actual content of an object passed to a mock, and it's just as useful for testing side-effects and indirect interactions – for example, when a method returns nothing but still has to send something to another component!
See you at the next pill! ☕