Tìm hiểu cách hoạt động của các Mockito Argument Matcher như any(), eq() và ArgumentCaptor trong Java để viết unit test linh hoạt và hiệu quả.
Giới thiệu về Mockito Argument Matchers
Trong quá trình viết Unit Test cho ứng dụng Java, Mockito Argument Matchers giúp bạn thiết lập hành vi cho các mock object linh hoạt hơn. Thay vì phải truyền chính xác một giá trị cố định, bạn có thể sử dụng các matcher như any(), eq(), hoặc ArgumentCaptor để kiểm tra hoặc giả lập dữ liệu trả về một cách linh hoạt.
1. Sử dụng matcher any()
Matcher any() được sử dụng khi bạn không quan tâm đến giá trị cụ thể của tham số truyền vào phương thức, miễn là tham số đó đúng kiểu dữ liệu.
Ví dụ: Giả sử bạn muốn giả lập hành vi cho phương thức getUserById(String id) của UserService:
// Giả lập trả về user mock với bất kỳ chuỗi ID nào
when(userService.getUserById(any(String.class))).thenReturn(new User("Test User"));
// Kiểm tra kết quả
User user = userService.getUserById("12345");
assertNotNull(user);
assertEquals("Test User", user.getName());
Ngoài any(Class), Mockito còn cung cấp các hàm viết gọn như anyString(), anyInt(), anyList(), v.v.
2. Kết hợp giá trị cụ thể với matcher eq()
Một quy tắc quan trọng trong Mockito: Nếu bạn sử dụng Argument Matcher cho một tham số, tất cả các tham số khác trong phương thức đó cũng phải sử dụng Matcher.
Nếu muốn kết hợp một giá trị cố định với một matcher khác, bạn phải bọc giá trị cố định đó trong eq().
Ví dụ:
// SAI: Sẽ gây ra lỗi InvalidUseOfMatchersException
when(notificationService.sendNotification("EMAIL", anyString())).thenReturn(true);
// ĐÚNG: Sử dụng eq() cho giá trị cố định "EMAIL"
when(notificationService.sendNotification(eq("EMAIL"), anyString())).thenReturn(true);
3. Bắt và kiểm tra tham số với ArgumentCaptor
Khi bạn muốn kiểm tra (verify) nội dung chi tiết của tham số được truyền vào phương thức mock sau khi thực thi, ArgumentCaptor là lựa chọn tối ưu.
Các bước sử dụng ArgumentCaptor:
- Khởi tạo
ArgumentCaptorcho kiểu dữ liệu tương ứng. - Sử dụng
captor.capture()trong lệnhverify(). - Lấy giá trị đã bắt bằng
captor.getValue()để kiểm tra bằng assertion.
Ví dụ:
// 1. Khởi tạo ArgumentCaptor
ArgumentCaptor<User> userCaptor = ArgumentCaptor.forClass(User.class);
// Thực thi phương thức cần test
userController.registerUser("john_doe", "john@example.com");
// 2. Bắt tham số được truyền vào userRepository.save()
verify(userRepository).save(userCaptor.capture());
// 3. Kiểm tra giá trị tham số đã được bắt
User capturedUser = userCaptor.getValue();
assertEquals("john_doe", capturedUser.getUsername());
assertEquals("john@example.com", capturedUser.getEmail());
Lưu ý quan trọng khi dùng Argument Matchers
- Chỉ sử dụng trong
when()hoặcverify(): Bạn không nên gọi Argument Matchers ngoài các câu lệnh stubbing hoặc verification của Mockito. - Tuân thủ quy tắc đồng bộ tham số: Đảm bảo toàn bộ tham số của phương thức đều dùng matcher nếu có ít nhất một matcher được sử dụng.
Việc làm chủ any(), eq() và ArgumentCaptor sẽ giúp bộ Unit Test của bạn trở nên rõ ràng, dễ bảo trì và xử lý tốt các kịch bản kiểm thử phức tạp.
Ngày phát hành: 19/05/2026
Nguồn: www.digitalocean.com