Mockito ArgumentMatchers

1. Khái quát chung

Đây hướng dẫn chương trình làm thế nào để sử dụng ArgumentMatcher và làm thế nào nó khác với ArgumentCaptor .

Để biết phần giới thiệu về Mockito framework, vui lòng tham khảo bài viết này.

2. Sự phụ thuộc của Maven

Chúng tôi cần thêm một cấu phần duy nhất:

 org.mockito mockito-core 2.21.0 test 

Bạn có thể tìm thấy phiên bản mới nhất của Mockito trên Maven Central .

3. ArgumentMatchers

Có thể định cấu hình một phương pháp mô phỏng theo nhiều cách khác nhau. Một trong số đó là trả về các giá trị cố định:

doReturn("Flower").when(flowerService).analyze("poppy");

Trong ví dụ trên, Chuỗi “Hoa” chỉ được trả lại khi dịch vụ phân tích nhận được Chuỗi “anh túc”.

Nhưng có thể chúng ta cần phản hồi với một phạm vi giá trị rộng hơn hoặc các giá trị chưa biết trước .

Trong tất cả các trường hợp này, chúng ta có thể định cấu hình các phương thức bị chế nhạo của mình bằng các trình so khớp đối số :

when(flowerService.analyze(anyString())).thenReturn("Flower");

Bây giờ, do đối số anyString so khớp, kết quả sẽ giống nhau cho dù chúng ta chuyển giá trị nào để phân tích. ArgumentMatchers cho phép chúng tôi xác minh hoặc sơ khai linh hoạt.

Trong trường hợp một phương thức có nhiều đối số, thì không thể sử dụng ArgumentMatchers chỉ cho một số đối số . Mockito đòi hỏi bạn phải cung cấp tất cả các đối bằng cách quẹt hoặc bằng giá trị chính xác.

Một ví dụ tiếp theo là một cách tiếp cận không chính xác cho điều này:

abstract class FlowerService { public abstract boolean isABigFlower(String name, int petals); } FlowerService mock = mock(FlowerService.class); when(mock.isABigFlower("poppy", anyInt())).thenReturn(true);

Để khắc phục và giữ cho tên Chuỗi “anh túc” như mong muốn, chúng tôi sẽ sử dụng eq matcher :

when(mock.isABigFlower(eq("poppy"), anyInt())).thenReturn(true);

Có thêm hai điểm để chăm sóc khi quẹt được sử dụng:

  • Chúng tôi không thể sử dụng chúng như một giá trị trả về , một giá trị chính xác là bắt buộc khi thực hiện lệnh gọi
  • Cuối cùng, chúng tôi không thể sử dụng trình khớp đối số bên ngoài xác minh hoặc sơ khai

Trong trường hợp cuối cùng, Mockito sẽ phát hiện đối số đặt sai vị trí và ném ra một lỗi không hợp lệ (InvalidUseOfMatchersException) .

Một ví dụ xấu có thể là:

String orMatcher = or(eq("poppy"), endsWith("y")); verify(mock).analyze(orMatcher);

Cách triển khai đoạn mã trên là:

verify(mock).analyze(or(eq("poppy"), endsWith("y")));

Mockito cũng cung cấp các Đối tượng bổ sung để triển khai các phép toán logic phổ biến ('không phải', 'và', 'hoặc') trên ArgumentMatcher phù hợp với cả kiểu nguyên thủy và không nguyên thủy:

verify(mock).analyze(or(eq("poppy"), endsWith("y")));

4. Trình so khớp đối số tùy chỉnh

Việc tạo so khớp của chúng tôi có thể tốt để chọn cách tiếp cận tốt nhất có thể cho một kịch bản nhất định và tạo ra thử nghiệm chất lượng cao nhất , sạch sẽ và có thể bảo trì được.

Ví dụ, chúng ta có thể có một MessageController để gửi tin nhắn. Nó sẽ nhận được một MessageDTO , và từ đó, nó sẽ tạo một tin nhắn để gửi bởi MessageService .

Việc xác minh của chúng tôi sẽ đơn giản, hãy xác minh rằng chúng tôi đã gọi MessageService chính xác 1 lần với bất kỳ Thông báo nào:

verify(messageService, times(1)).deliverMessage(any(Message.class));

Bởi vì các tin nhắn được xây dựng bên trong các phương pháp dưới sự kiểm tra , chúng tôi buộc phải sử dụng bất kỳ như các khớp .

Cách tiếp cận này không cho phép chúng tôi xác thực dữ liệu bên trong Message , dữ liệu này có thể khác so với dữ liệu bên trong MessageDTO .

Vì lý do đó, chúng tôi sẽ triển khai trình so khớp đối số tùy chỉnh:

public class MessageMatcher implements ArgumentMatcher { private Message left; // constructors @Override public boolean matches(Message right) { return left.getFrom().equals(right.getFrom()) && left.getTo().equals(right.getTo()) && left.getText().equals(right.getText()) && right.getDate() != null && right.getId() != null; } }

Để sử dụng trình so khớp của chúng tôi, chúng tôi cần sửa đổi thử nghiệm của mình và thay thế bất kỳ thử nghiệm nào bằng argThat :

verify(messageService, times(1)).deliverMessage(argThat(new MessageMatcher(message)));

Bây giờ chúng tôi biết cá thể Message của chúng tôi sẽ có cùng dữ liệu với MessageDTO của chúng tôi .

5. Trình khớp đối số tùy chỉnh so với Trình ghi đối số

Cả hai kỹ thuật so khớp đối số tùy chỉnhArgumentCaptor đều có thể được sử dụng để đảm bảo một số đối số nhất định đã được chuyển tới mocks.

Tuy nhiên, ArgumentCaptor có thể phù hợp hơn nếu chúng ta cần nó xác nhận trên các giá trị đối số để hoàn tất xác minh hoặc trình so khớp đối số tùy chỉnh của chúng tôi không có khả năng được sử dụng lại .

Trình so khớp đối số tùy chỉnh thông qua ArgumentMatcher thường tốt hơn cho việc khai báo.

6. Kết luận

Trong bài viết này, chúng tôi đã khám phá một tính năng của Mockito , ArgumentMatcher và sự khác biệt của nó với ArgumentCaptor .

Như mọi khi, mã nguồn đầy đủ của các ví dụ có sẵn trên GitHub.