Bird
Raised Fist0
JUnittesting~15 mins

@MockBean for Spring mocking in JUnit - Build an Automation Script

Choose your learning style10 modes available
Verify service method behavior using @MockBean in Spring Boot test
Preconditions (2)
Step 1: Annotate the test class with @SpringBootTest.
Step 2: Use @MockBean to mock the UserRepository bean.
Step 3: Stub the UserRepository's findById method to return a User object when called with a specific ID.
Step 4: Call the UserService's getUserById method with the same ID.
Step 5: Verify that the returned User object matches the stubbed data.
✅ Expected Result: The test passes confirming that UserService returns the expected User object using the mocked UserRepository.
Automation Requirements - JUnit 5 with Spring Boot Test
Assertions Needed:
Assert that the User object returned by UserService is not null.
Assert that the User object's fields match the stubbed values.
Best Practices:
Use @MockBean to replace Spring beans with mocks in the application context.
Use Mockito's when-thenReturn syntax to stub methods.
Use @SpringBootTest to load the full application context.
Avoid hardcoding values; use constants or variables for test data.
Use descriptive method names for test clarity.
Automated Solution
JUnit
import static org.mockito.Mockito.when;
import static org.junit.jupiter.api.Assertions.*;

import java.util.Optional;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;

@SpringBootTest
class UserServiceTest {

    @Autowired
    private UserService userService;

    @MockBean
    private UserRepository userRepository;

    @Test
    void testGetUserById_ReturnsUser() {
        // Arrange
        Long userId = 1L;
        User mockUser = new User(userId, "Alice", "alice@example.com");
        when(userRepository.findById(userId)).thenReturn(Optional.of(mockUser));

        // Act
        User result = userService.getUserById(userId);

        // Assert
        assertNotNull(result, "User should not be null");
        assertEquals(userId, result.getId(), "User ID should match");
        assertEquals("Alice", result.getName(), "User name should match");
        assertEquals("alice@example.com", result.getEmail(), "User email should match");
    }
}

// Supporting classes for context
record User(Long id, String name, String email) {}

interface UserRepository {
    Optional<User> findById(Long id);
}

class UserService {
    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User getUserById(Long id) {
        return userRepository.findById(id).orElse(null);
    }
}

The test class is annotated with @SpringBootTest to load the Spring context.

@MockBean replaces the UserRepository bean with a Mockito mock.

We stub the findById method to return a known User object when called with userId.

The service method getUserById is called, which uses the mocked repository.

Assertions check that the returned user is not null and matches the stubbed data.

This setup tests the service logic independently from the real database.

Common Mistakes - 3 Pitfalls
Using @Mock instead of @MockBean in Spring Boot test
{'mistake': 'Not stubbing the mock method before calling the service', 'why_bad': 'Without stubbing, the mock returns default values (null), causing NullPointerExceptions or wrong test results.', 'correct_approach': "Use Mockito's when-thenReturn to define expected mock behavior before invoking the service."}
Not annotating the test class with @SpringBootTest
Bonus Challenge

Now add data-driven testing with 3 different user IDs and expected user data

Show Hint

Practice

(1/5)
1. What is the main purpose of using @MockBean in Spring tests?
easy
A. To replace a real Spring bean with a mock during testing
B. To create a new Spring bean in the application context
C. To run the application without any beans
D. To automatically generate test data for the application

Solution

  1. Step 1: Understand the role of @MockBean

    @MockBean is used to replace a real Spring bean with a mock version during tests to isolate the tested component.
  2. Step 2: Compare options with the purpose

    Only To replace a real Spring bean with a mock during testing correctly describes this purpose. Other options describe unrelated behaviors.
  3. Final Answer:

    To replace a real Spring bean with a mock during testing -> Option A
  4. Quick Check:

    @MockBean replaces beans = A [OK]
Hint: Remember: @MockBean swaps real beans with mocks [OK]
Common Mistakes:
  • Thinking @MockBean creates new beans instead of replacing
  • Confusing @MockBean with test data generation
  • Assuming @MockBean disables all beans
2. Which of the following is the correct way to declare a mock bean in a Spring test class?
easy
A. @Mock private MyService myService;
B. @InjectMocks private MyService myService;
C. @Autowired private MyService myService;
D. @MockBean private MyService myService;

Solution

  1. Step 1: Identify the correct annotation for Spring mock beans

    @MockBean is the Spring Boot test annotation to create mock beans in the application context.
  2. Step 2: Check the options

    @MockBean private MyService myService; uses @MockBean correctly. Options A and D are Mockito annotations but not for Spring context replacement. @Autowired private MyService myService; is for injecting real beans.
  3. Final Answer:

    @MockBean private MyService myService; -> Option D
  4. Quick Check:

    @MockBean syntax = B [OK]
Hint: Use @MockBean for Spring context mocks, not @Mock or @InjectMocks [OK]
Common Mistakes:
  • Using @Mock instead of @MockBean in Spring tests
  • Confusing @Autowired with mocking
  • Using @InjectMocks outside Mockito context
3. Given the following test code snippet, what will be the output of myService.getData() if myService is annotated with @MockBean and no behavior is defined?
@MockBean
private MyService myService;

@Test
void test() {
    System.out.println(myService.getData());
}
medium
A. Throws NullPointerException
B. Actual data from MyService implementation
C. null
D. Empty string

Solution

  1. Step 1: Understand default behavior of @MockBean mocks

    @MockBean creates a Mockito mock. By default, methods return null for objects unless stubbed.
  2. Step 2: Analyze the code snippet

    No behavior is defined for getData(), so it returns null by default.
  3. Final Answer:

    null -> Option C
  4. Quick Check:

    Unstubbed mock method returns null = C [OK]
Hint: Unstubbed mock methods return null by default [OK]
Common Mistakes:
  • Expecting real method execution instead of mock
  • Assuming default return is empty string or exception
  • Confusing @MockBean with real bean injection
4. Identify the error in the following Spring test class using @MockBean:
@SpringBootTest
public class UserServiceTest {

    @MockBean
    private UserRepository userRepository;

    @Test
    public void testFindUser() {
        when(userRepository.findById(1L)).thenReturn(Optional.of(new User()));
        // test logic
    }
}
medium
A. Missing @RunWith(SpringRunner.class) or @ExtendWith(SpringExtension.class)
B. No error, the code is correct
C. UserRepository should be annotated with @Autowired, not @MockBean
D. Incorrect use of when() without MockitoAnnotations.initMocks()

Solution

  1. Step 1: Check Spring test setup requirements

    @SpringBootTest provides the Spring context and necessary extensions (meta-annotated with @ExtendWith(SpringExtension.class)), enabling @MockBean.
  2. Step 2: Analyze the code

    @MockBean is used correctly. Stubbing with when().thenReturn() works without additional Mockito initialization in Spring Boot tests.
  3. Final Answer:

    No error, the code is correct -> Option B
  4. Quick Check:

    @SpringBootTest enables @MockBean = D [OK]
Hint: @SpringBootTest is sufficient for @MockBean tests [OK]
Common Mistakes:
  • Thinking @RunWith or @ExtendWith is required with @SpringBootTest
  • Using MockitoAnnotations.initMocks() with @MockBean
  • Annotating mocks with @Autowired
5. You have a Spring service OrderService that depends on PaymentService. You want to test OrderService without calling the real PaymentService. Which approach correctly uses @MockBean to achieve this?
@SpringBootTest
public class OrderServiceTest {

    @Autowired
    private OrderService orderService;

    // What should be here?

    @Test
    public void testPlaceOrder() {
        when(paymentService.processPayment(any())).thenReturn(true);
        boolean result = orderService.placeOrder(new Order());
        assertTrue(result);
    }
}
hard
A. @MockBean private PaymentService paymentService;
B. @Mock private PaymentService paymentService;
C. @Autowired private PaymentService paymentService;
D. No declaration needed; real PaymentService will be used

Solution

  1. Step 1: Understand the goal

    We want to test OrderService but replace PaymentService with a mock to avoid real calls.
  2. Step 2: Choose the correct annotation

    @MockBean replaces the Spring bean in the context with a mock, so @MockBean private PaymentService paymentService; is correct. @Mock is Mockito-only and won't replace Spring beans. @Autowired injects real bean. No declaration uses real service.
  3. Final Answer:

    @MockBean private PaymentService paymentService; -> Option A
  4. Quick Check:

    Use @MockBean to mock Spring dependencies = D [OK]
Hint: Use @MockBean to mock Spring dependencies in tests [OK]
Common Mistakes:
  • Using @Mock instead of @MockBean for Spring beans
  • Injecting real beans instead of mocks
  • Not declaring the mock bean at all
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