0
0
JUnittesting~15 mins

Choosing the right test double in JUnit - Build an Automation Script

Choose your learning style9 modes available
Verify behavior of OrderProcessor using a mock PaymentService
Preconditions (2)
Step 1: Create a mock PaymentService
Step 2: Configure mock to return true when processPayment is called with any amount
Step 3: Inject mock PaymentService into OrderProcessor
Step 4: Call OrderProcessor.placeOrder with amount 100.0
Step 5: Verify that OrderProcessor calls processPayment on PaymentService with 100.0
Step 6: Verify that placeOrder returns true
✅ Expected Result: OrderProcessor.placeOrder returns true and processPayment is called once with 100.0
Automation Requirements - JUnit 5 with Mockito
Assertions Needed:
Assert that placeOrder returns true
Verify that processPayment is called once with 100.0
Best Practices:
Use Mockito to create mocks
Use @BeforeEach to setup test objects
Use verify() to check method calls
Keep tests isolated and focused
Automated Solution
JUnit
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

interface PaymentService {
    boolean processPayment(double amount);
}

class OrderProcessor {
    private final PaymentService paymentService;

    public OrderProcessor(PaymentService paymentService) {
        this.paymentService = paymentService;
    }

    public boolean placeOrder(double amount) {
        return paymentService.processPayment(amount);
    }
}

public class OrderProcessorTest {
    private PaymentService paymentServiceMock;
    private OrderProcessor orderProcessor;

    @BeforeEach
    void setup() {
        paymentServiceMock = mock(PaymentService.class);
        orderProcessor = new OrderProcessor(paymentServiceMock);
    }

    @Test
    void testPlaceOrderCallsProcessPayment() {
        when(paymentServiceMock.processPayment(anyDouble())).thenReturn(true);

        boolean result = orderProcessor.placeOrder(100.0);

        assertTrue(result, "placeOrder should return true");
        verify(paymentServiceMock, times(1)).processPayment(100.0);
    }
}

This test uses Mockito to create a mock of the PaymentService interface. In the @BeforeEach method, the mock is created and injected into the OrderProcessor instance.

In the test method, we configure the mock to return true for any payment amount using when(...).thenReturn(true). Then we call placeOrder(100.0) and assert that it returns true.

Finally, we verify that the processPayment method was called exactly once with the argument 100.0. This confirms that OrderProcessor correctly delegates payment processing to the PaymentService.

This approach uses a mock test double to isolate OrderProcessor from the real PaymentService, allowing us to test behavior without side effects.

Common Mistakes - 3 Pitfalls
Not using a mock and calling the real PaymentService
{'mistake': 'Not verifying that processPayment was called', 'why_bad': "Without verification, you don't confirm that the interaction with the dependency happened as expected.", 'correct_approach': "Use Mockito's verify() method to check that processPayment was called with correct arguments."}
Hardcoding return values without using when().thenReturn()
Bonus Challenge

Now add data-driven testing with 3 different payment amounts: 50.0, 100.0, and 200.0

Show Hint