Bird
Raised Fist0
JUnittesting~15 mins

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

Choose your learning style10 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

Practice

(1/5)
1. Which test double should you use in JUnit when you want to replace a real object and verify that certain methods were called during the test?
easy
A. Mock
B. Stub
C. Fake
D. Spy

Solution

  1. Step 1: Understand the purpose of mocks

    Mocks are used to fake behavior and verify interactions, such as method calls.
  2. Step 2: Compare with other test doubles

    Stubs provide fixed responses, fakes have working implementations, spies record calls but mocks are designed for verification.
  3. Final Answer:

    Mock -> Option A
  4. Quick Check:

    Verify calls = Mock [OK]
Hint: Mocks verify calls; stubs just return data [OK]
Common Mistakes:
  • Confusing stubs with mocks
  • Using fake when verification is needed
  • Thinking spies are the same as mocks
2. Which of the following is the correct way to create a stub in JUnit using Mockito?
easy
A. spy(new Service());
B. when(service.getData()).thenReturn("data");
C. mock(Service.class);
D. verify(service).getData();

Solution

  1. Step 1: Identify stub creation syntax

    Stubs return fixed data; in Mockito, use when(...).thenReturn(...) to stub a method.
  2. Step 2: Check other options

    Verify checks calls, mock creates mocks, spy wraps real objects; only when().thenReturn() stubs.
  3. Final Answer:

    when(service.getData()).thenReturn("data"); -> Option B
  4. Quick Check:

    Stub method = when().thenReturn() [OK]
Hint: Stubs use when().thenReturn() syntax [OK]
Common Mistakes:
  • Using verify() to stub methods
  • Confusing mock() with stub setup
  • Using spy() instead of stub
3. Given the following JUnit test code snippet using Mockito, what will be the output of the assertion?
List<String> list = mock(List.class);
when(list.size()).thenReturn(5);
assertEquals(5, list.size());
medium
A. Test passes because size() returns 5
B. Test fails because size() returns 0 by default
C. Test throws NullPointerException
D. Test fails due to syntax error

Solution

  1. Step 1: Analyze mock behavior

    The list is mocked, and size() is stubbed to return 5.
  2. Step 2: Check assertion

    assertEquals(5, list.size()) compares 5 with stubbed return 5, so it passes.
  3. Final Answer:

    Test passes because size() returns 5 -> Option A
  4. Quick Check:

    Stubbed method returns set value [OK]
Hint: Stubbed methods return set values, so assertion passes [OK]
Common Mistakes:
  • Assuming default mock returns 0
  • Expecting real method call on mock
  • Confusing mock with spy behavior
4. Identify the error in this JUnit test using Mockito:
@Test
void testServiceCall() {
  Service service = mock(Service.class);
  service.process();
  verify(service.process());
}
medium
A. Mock creation syntax is wrong
B. Missing stub for process() method
C. process() method cannot be mocked
D. Incorrect use of verify; should be verify(service).process();

Solution

  1. Step 1: Check verify syntax

    verify() expects the mock object, then method call separately: verify(service).process();
  2. Step 2: Identify error in code

    Current code calls verify(service.process()), which is incorrect syntax and causes compile error.
  3. Final Answer:

    Incorrect use of verify; should be verify(service).process(); -> Option D
  4. Quick Check:

    verify syntax = verify(mock).method() [OK]
Hint: verify() needs mock object, then method call separately [OK]
Common Mistakes:
  • Calling verify with method call inside
  • Forgetting to mock the object
  • Confusing stub and verify usage
5. You want to test a payment processing system. The payment gateway is an external service that charges real money. Which test double should you use in your JUnit tests to avoid real charges but still verify that the payment method was called correctly?
hard
A. Use a stub to return a fixed success response
B. Use a fake with a simple in-memory implementation
C. Use a mock to verify the payment method call
D. Use a spy to wrap the real payment gateway

Solution

  1. Step 1: Understand test goal

    We want to avoid real charges but verify the payment method was called.
  2. Step 2: Choose test double type

    Mocks fake behavior and verify calls, perfect for checking method calls without real effects.
  3. Step 3: Compare other options

    Stubs return fixed data but don't verify calls; fakes have real logic; spies call real methods, risking real charges.
  4. Final Answer:

    Use a mock to verify the payment method call -> Option C
  5. Quick Check:

    Verify calls without real effect = Mock [OK]
Hint: Mocks verify calls without real side effects [OK]
Common Mistakes:
  • Using spy risks real external calls
  • Using stub misses call verification
  • Choosing fake adds unnecessary complexity
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard