Mockito Mocks and Stubs

Why Mocks

A service usually depends on other things: a repository (DB), a payment gateway (HTTP), an email sender. A unit test should not hit a real DB or charge a card. A mock is a fake object created by Mockito that returns what you tell it to (stubbing) and records how it was called.

Test ──► OrderService ──► ProductRepository   (mock: returns a fixed product)
                     └──► PaymentGateway      (mock: returns SUCCESS / throws)
                     └──► EmailSender         (mock: we only verify it was called)

Stubbing with when/thenReturn

@ExtendWith(MockitoExtension.class)
class OrderServiceTest {

    @Mock ProductRepository productRepository;
    @Mock PaymentGateway paymentGateway;
    @Mock EmailSender emailSender;
    @InjectMocks OrderService orderService;          // real object, mocks injected via constructor

    @Test
    void placesOrderWhenStockAndPaymentOk() {
        // Arrange
        Product phone = new Product(1L, "Phone", new BigDecimal("15999"), 5);
        when(productRepository.findById(1L)).thenReturn(Optional.of(phone));
        when(paymentGateway.charge(any(), eq(new BigDecimal("15999")))).thenReturn(PaymentStatus.SUCCESS);

        // Act
        Order order = orderService.placeOrder("ravi", 1L, 1);

        // Assert
        assertEquals(OrderStatus.CONFIRMED, order.status());
        assertEquals(4, phone.stock());
    }

    @Test
    void failsWhenProductMissing() {
        when(productRepository.findById(99L)).thenReturn(Optional.empty());
        assertThrows(ProductNotFoundException.class, () -> orderService.placeOrder("ravi", 99L, 1));
    }

    @Test
    void paymentGatewayDown() {
        when(productRepository.findById(1L)).thenReturn(Optional.of(new Product(1L, "Phone", BigDecimal.TEN, 5)));
        when(paymentGateway.charge(any(), any())).thenThrow(new GatewayTimeoutException("Razorpay timeout"));
        Order order = orderService.placeOrder("ravi", 1L, 1);
        assertEquals(OrderStatus.PAYMENT_PENDING, order.status());
    }
}

Stubbing Cheat Sheet

CodeEffect
when(m.call()).thenReturn(x)return x
thenReturn(a, b, c)a on 1st call, b on 2nd, c afterwards
thenThrow(ex)throw
thenAnswer(inv -> ...)compute the answer from the arguments
doThrow(ex).when(m).voidMethod()stub void methods
any(), eq(x), anyString(), argThat(pred)argument matchers (if one argument uses a matcher, all must)

Note: Mockito (with MockitoExtension) uses strict stubs: an unused when(...) fails the test with UnnecessaryStubbingException, which keeps tests clean.