Mockito verify(): How to Assert Method Calls in Unit Tests
- verify(mock).method() asserts the method was called exactly once. Add a verification mode (times, never, atLeast) to assert different counts.
- Argument matchers (any(), anyString(), eq(), argThat()) must be used consistently β if one argument uses a matcher, all must.
- ArgumentCaptor captures the actual argument passed to a mock method so you can assert on generated or computed values.
account.getBalance() equals 1000, that's asserting state. When a test checks that notificationService.sendEmail() was called exactly once with the right email address, that's asserting behaviour β and verify() is the tool for it.
There are two schools of thought on verify() in unit tests. One says: verify everything β assert that every collaborator method was called as expected. The other says: verify only the meaningful side effects β calling a payment processor, sending a notification β and trust that state assertions cover the rest.
After ten years of writing and reviewing Java tests, I'm firmly in the second camp. Verifying every internal method call ties your tests to the implementation rather than the contract. When you refactor, tests break for reasons unrelated to correctness. Verify interactions that represent side effects your callers care about. Leave implementation details to state assertions.
Basic verify() and Verification Modes
The basic verify(mock).method(args) asserts the method was called exactly once with the given arguments. Verification modes control the count: times(n), atLeastOnce(), atLeast(n), atMost(n), never().
package io.thecodeforge.payment; import org.junit.jupiter.api.Test; import org.mockito.Mockito; import static org.mockito.Mockito.*; import static org.mockito.ArgumentMatchers.*; class PaymentProcessorTest { @Test void processPayment_successful_sendsConfirmationEmail() { // Arrange NotificationService notificationService = mock(NotificationService.class); AuditService auditService = mock(AuditService.class); PaymentProcessor processor = new PaymentProcessor(notificationService, auditService); PaymentRequest request = new PaymentRequest("customer-42", 100_00, "GBP"); // Act processor.processPayment(request); // Assert behaviour: confirm email was sent exactly once verify(notificationService, times(1)) .sendConfirmationEmail("customer-42", 100_00); // Assert audit was logged (at least once is sufficient here) verify(auditService, atLeastOnce()) .log(eq("PAYMENT_PROCESSED"), anyString()); // Assert the fraud check was never called for small amounts verify(auditService, never()) .flagForFraudReview(anyString()); } @Test void processPayment_largAmount_triggersFraudCheck() { NotificationService notificationService = mock(NotificationService.class); AuditService auditService = mock(AuditService.class); PaymentProcessor processor = new PaymentProcessor(notificationService, auditService); // Β£10,000 β above fraud threshold processor.processPayment( new PaymentRequest("customer-42", 10_000_00, "GBP")); // Fraud check must be triggered for large transactions verify(auditService, times(1)).flagForFraudReview("customer-42"); } }
PaymentProcessorTest > processPayment_successful_sendsConfirmationEmail PASSED
PaymentProcessorTest > processPayment_largAmount_triggersFraudCheck PASSED
Argument Matchers in verify()
Exact argument matching works for primitives and objects with correct equals() implementations. For everything else, Mockito's argument matchers give you flexibility: any(), anyString(), eq(), argThat() for custom predicates.
The rule that trips people up: you cannot mix exact values and matchers in the same method call. If one argument uses a matcher, all arguments must use matchers. Wrap exact values in eq().
package io.thecodeforge.order; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import static org.mockito.Mockito.*; import static org.mockito.ArgumentMatchers.*; import static org.junit.jupiter.api.Assertions.*; class OrderServiceTest { @Test void placeOrder_notifiesWarehouse_withCorrectDetails() { WarehouseService warehouse = mock(WarehouseService.class); OrderService orderService = new OrderService(warehouse); orderService.placeOrder(new Order("order-1", "SKU-42", 3)); // Mix of exact and matchers β ALL must use matchers when mixing verify(warehouse).dispatchRequest( eq("SKU-42"), // exact value wrapped in eq() eq(3), // exact value wrapped in eq() anyString() // any dispatch reference ); // Custom predicate with argThat() verify(warehouse).dispatchRequest( argThat(sku -> sku.startsWith("SKU-")), anyInt(), anyString() ); } @Test void placeOrder_capturesActualArguments() { WarehouseService warehouse = mock(WarehouseService.class); OrderService orderService = new OrderService(warehouse); orderService.placeOrder(new Order("order-1", "SKU-42", 3)); // ArgumentCaptor: capture the actual argument and assert on it ArgumentCaptor<DispatchRequest> captor = ArgumentCaptor.forClass(DispatchRequest.class); verify(warehouse).dispatch(captor.capture()); DispatchRequest captured = captor.getValue(); assertEquals("SKU-42", captured.getSku()); assertEquals(3, captured.getQuantity()); assertNotNull(captured.getDispatchId()); // Generated, can't use eq() } }
OrderServiceTest > placeOrder_capturesActualArguments PASSED
| Verification Mode | Meaning | Example |
|---|---|---|
| times(1) (default) | Called exactly once | verify(mock).method() |
| times(n) | Called exactly n times | verify(mock, times(3)).method() |
| never() | Never called | verify(mock, never()).method() |
| atLeastOnce() | Called at least once | verify(mock, atLeastOnce()).method() |
| atLeast(n) | Called at least n times | verify(mock, atLeast(2)).method() |
| atMost(n) | Called at most n times | verify(mock, atMost(5)).method() |
π― Key Takeaways
- verify(mock).method() asserts the method was called exactly once. Add a verification mode (times, never, atLeast) to assert different counts.
- Argument matchers (any(), anyString(), eq(), argThat()) must be used consistently β if one argument uses a matcher, all must.
- ArgumentCaptor captures the actual argument passed to a mock method so you can assert on generated or computed values.
- Verify the meaningful side effects β payment processed, email sent, event published. Don't verify internal implementation details that would break on any refactor.
β Common Mistakes to Avoid
- βVerifying every internal method call β this ties tests to implementation, not contract. Refactoring breaks tests for no business-logic reason.
- βMixing exact values and argument matchers without wrapping the exact values in eq() β Mockito throws InvalidUseOfMatchersException.
- βCalling verify() before the system under test executes β verify() checks interactions that have already happened; it must come after the act step.
- βNot using ArgumentCaptor for generated values β trying to eq() a UUID or timestamp that the code generates will always fail.
Interview Questions on This Topic
- QWhat is the difference between Mockito when() and verify()?
- QHow do you verify a method was called exactly three times in Mockito?
- QWhen would you use ArgumentCaptor instead of argument matchers?
- QWhy might over-verifying in tests be an antipattern?
Frequently Asked Questions
What does Mockito verify() do?
verify() asserts that a method on a mock object was called after the system under test ran. It checks the interaction happened β the method was invoked, optionally with specific arguments, optionally a specific number of times. If the method wasn't called as specified, the test fails with a WantedButNotInvoked or TooManyActualInvocations exception.
How do I verify a method was never called in Mockito?
Use verify(mock, never()).methodName(). This asserts the method was never invoked during the test. Combine with any() if you don't care about the arguments: verify(mock, never()).methodName(any()).
What is ArgumentCaptor and when should I use it?
ArgumentCaptor captures the actual argument passed to a mock method so you can make assertions on it. Use it when the argument is generated by the code under test (a UUID, a timestamp, a computed object) and you can't predict the exact value at test-write time. Call captor.capture() in the verify(), then captor.getValue() to get what was actually passed.
Developer and founder of TheCodeForge. I built this site because I was tired of tutorials that explain what to type without explaining why it works. Every article here is written to make concepts actually click.