Hotline:
08.8803.8803
T2-T7:
8h30 - 20h30
| CN:
8h30 - 17h00

Mock trong Spring Test là gì

admin . 7:37 am

🌟 Mock trong Spring Test là gì?

Mock (giả lập) là kỹ thuật tạo đối tượng giả để thay thế phụ thuộc thực tế (database, API ngoài…) trong quá trình kiểm thử. Mục đích chính:

  • Cô lập code cần test: Tập trung vào logic chính, không lo lỗi từ bên ngoài.
  • Kiểm soát hành vi: Định nghĩa sẵn kết quả trả về hoặc lỗi.
  • Tăng tốc độ test: Tránh gọi dịch vụ chậm (như kết nối mạng).

Trong Spring, ta dùng Mockito (thư viện phổ biến) kết hợp @SpringBootTest hoặc @WebMvcTest.


🔧 Ví dụ dễ hiểu: Test Service với Mock Repository

Scenario: Kiểm thử UserService không cần kết nối database thật.

Bước 1: Định nghĩa lớp cần test

@Service
public class UserService {
    @Autowired
    private UserRepository userRepo; // Dependency cần mock

    public User getUserById(Long id) {
        return userRepo.findById(id).orElseThrow(
            () -> new RuntimeException("User not found")
        );
    }
}

Bước 2: Tạo test class với Mockito

@ExtendWith(MockitoExtension.class) // Kích hoạt Mockito
class UserServiceTest {

    @Mock
    private UserRepository userRepo; // Tạo mock Repository

    @InjectMocks
    private UserService userService; // Inject mock vào Service

    @Test
    void getUserById_ShouldReturnUser() {
        // 1. Thiết lập dữ liệu giả
        User fakeUser = new User(1L, "Tuan Nguyen");
        when(userRepo.findById(1L)).thenReturn(Optional.of(fakeUser));

        // 2. Gọi method thật
        User result = userService.getUserById(1L);

        // 3. Kiểm tra kết quả
        assertEquals("Tuan Nguyen", result.getName());
        verify(userRepo).findById(1L); // Xác nhận đã gọi repository
    }
}

Giải thích từng phần:

Công cụChức năng
@MockTạo đối tượng giả cho UserRepository
@InjectMocksĐưa mock vào UserService (tự động inject dependencies)
when(...).thenReturnĐịnh nghĩa: “Khi gọi findById(1) → trả về fakeUser
verify()Kiểm tra xem repository đã được gọi đúng tham số chưa

🚨 Ví dụ xử lý lỗi với Mock

@Test
void getUserById_ShouldThrowException() {
    // Thiết lập mock: không tìm thấy user
    when(userRepo.findById(999L)).thenReturn(Optional.empty());

    // Kiểm tra ngoại lệ
    assertThrows(RuntimeException.class, () -> {
        userService.getUserById(999L);
    });
}

📌 Tại sao dùng Mock?

  • Test nhanh hơn 10x: Không cần chờ database khởi động.
  • Bắt lỗi chính xác: Biết ngay lỗi ở service hay do database.
  • Coverage 100%: Test được cả trường hợp “không tìm thấy dữ liệu”.

💡 Tip: Dùng kết hợp @DataJpaTest cho test repository thật, @WebMvcTest + mock cho controller.