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 |
---|---|
@Mock | Tạ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.