Homeβ€Ί Javaβ€Ί Mockito verify(): How to Assert Method Calls in Unit Tests

Mockito verify(): How to Assert Method Calls in Unit Tests

Where developers are forged. Β· Structured learning Β· Free forever.
πŸ“ Part of: Advanced Java β†’ Topic 25 of 26
Learn how to use Mockito verify() to assert that methods were called, called with specific arguments, called a specific number of times, or never called.
βš™οΈ Intermediate β€” basic Java knowledge assumed
In this tutorial, you'll learn:
  • 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.
✦ Plain-English analogy ✦ Real code with output ✦ Interview questions
⚑ Quick Answer
Mockito verify() is how you assert behaviour, not state. When a test checks that 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().

PaymentProcessorTest.java Β· JAVA
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
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");
    }
}
β–Ά Output
# Test passes β€” both verifications satisfied
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().

OrderServiceTest.java Β· JAVA
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
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()
    }
}
β–Ά Output
OrderServiceTest > placeOrder_notifiesWarehouse_withCorrectDetails PASSED
OrderServiceTest > placeOrder_capturesActualArguments PASSED
πŸ”₯
Use ArgumentCaptor when you need to assert on generated valuesWhen the code under test generates a value (an ID, a timestamp, a computed field) and passes it to a collaborator, you can't use eq() because you don't know the value at test-write time. ArgumentCaptor captures the actual argument that was passed, so you can assert on its structure or properties after the fact. This is one of the most useful patterns in Mockito and one of the most underused.
Verification ModeMeaningExample
times(1) (default)Called exactly onceverify(mock).method()
times(n)Called exactly n timesverify(mock, times(3)).method()
never()Never calledverify(mock, never()).method()
atLeastOnce()Called at least onceverify(mock, atLeastOnce()).method()
atLeast(n)Called at least n timesverify(mock, atLeast(2)).method()
atMost(n)Called at most n timesverify(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.

πŸ”₯
Naren Founder & Author

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.

← PreviousJUnit 5 Annotations: @Test, @BeforeEach, @AfterEach and MoreNext β†’Unit Testing vs Integration Testing: Key Differences
Forged with πŸ”₯ at TheCodeForge.io β€” Where Developers Are Forged