0
0
JUnittesting~15 mins

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

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