Careeroza
Verifying Interactions
verify
For methods that return nothing (sending email, publishing an event), check that the mock was called correctly with verify.
@Test
void sendsConfirmationEmailOnce() {
when(productRepository.findById(1L)).thenReturn(Optional.of(phone));
when(paymentGateway.charge(any(), any())).thenReturn(PaymentStatus.SUCCESS);
orderService.placeOrder("ravi", 1L, 1);
verify(emailSender, times(1)).send(eq("ravi"), contains("Order confirmed"));
verify(productRepository).save(phone); // times(1) is the default
verifyNoMoreInteractions(emailSender);
}
@Test
void noEmailWhenPaymentFails() {
when(productRepository.findById(1L)).thenReturn(Optional.of(phone));
when(paymentGateway.charge(any(), any())).thenReturn(PaymentStatus.DECLINED);
orderService.placeOrder("ravi", 1L, 1);
verify(emailSender, never()).send(any(), any());
}ArgumentCaptor
@Captor ArgumentCaptor<OrderPlacedEvent> eventCaptor;
@Test
void publishesEventWithCorrectTotal() {
// ... arrange stubs ...
orderService.placeOrder("ravi", 1L, 2);
verify(eventPublisher).publish(eventCaptor.capture());
OrderPlacedEvent event = eventCaptor.getValue();
assertEquals(new BigDecimal("31998"), event.total());
assertEquals("ravi", event.customer());
}| Verification mode | Meaning |
|---|---|
times(n), never() | exactly n / zero calls |
atLeast(n), atMost(n) | bounds |
inOrder(a, b).verify(...) | calls happened in this order |
verifyNoInteractions(mock) | the mock was never touched |
Mock, Spy, Fake
| Kind | What it is | Use |
|---|---|---|
Mock (@Mock) | all methods return defaults unless stubbed | external dependencies |
Spy (@Spy) | real object, some methods stubbed | legacy code, partial behaviour (use rarely) |
| Fake | a simple working implementation (in-memory repository) | when mocks get too complex |
Tip: Do not mock what you do not own (e.g. HttpClient internals) or simple value objects — mock your own interfaces (PaymentGateway) and wrap third-party APIs behind them.