Tags:

Cách sử dụng ArgumentCaptor trong mockito

Trong bài viết này chúng ta sẽ cùng nhau tìm hiểu cách sử dụng ArgumentCaptor trong mockito. Đây là một tính năng khá thú vị nhưng vì điều kiện sử dụng tính năng này không thường xuyên nên rất dễ quên.

Sử dụng ArgumentCaptor trong trường hợp nào?

ArgumentCaptor cho phép chúng ta theo dõi các tham số truyền vào một method.  ính năng này đặc biệt hữu ích khi chúng ta không thế truy cập các tham số này từ bên ngoài nhưng vẫn muốn kiểm tra giá trị của chúng khi truyền vào method.

Giả sử chúng ta có EmailService class dùng để gửi email được triển khai như sau

public class EmailService {

    private DeliveryPlatform platform;

    public EmailService(DeliveryPlatform platform) {
        this.platform = platform;
    }

    public void send(String to, String subject, String body, boolean html) {
        Format format = Format.TEXT_ONLY;
        if (html) {
            format = Format.HTML;
        }
        Email email = new Email(to, subject, body, format);
        platform.send(email);
    }

}

Setup unit-test

Để tìm hiểu cách sử dụng ArgumentCaptor trước tiên chúng ta cần setup unit-test tích hợp mockito

@ExtendWith(MockitoExtension.class)
public class EmailServiveTest {

    @Mock
    private DeliveryPlatform platform;

    @InjectMocks
    private EmailService emailService;

    
}

Kể từ phiên bản Junit 5 việc tích hợp mockito rất đơn giản, chúng ta chỉ cần sử dụng @ExtendWith kết hợp với MockitoExtension class do mockito phát triển.

Các bạn lưu ý rằng DeliveryPlatform là mock-object sẽ được inject vào EmailService object trong quá trình thực thi unit-test.

ArgumentCaptor object

Việc khởi tạo một ArgumentCaptor object giờ đây khá đơn giản, chúng ta cần sử dụng @Captor annotation chú thích lên object thuộc tính cần khởi tạo.

@Captor
ArgumentCaptor<Email> emailCaptor;

Áp dụng ArgumentCaptor

ArgumentCaptor cho phép chúng ta theo dõi giá trị của các tham số truyền vào một method được chỉ định. Để làm được điều này chúng ta cần kết hợp với Mockito.verify().

Ví dụ trong EmailService của chúng ta, hàm DeliveryPlatform#send() nhận vào một tham số là Email object và không trả về bất cứ dữ liệu nào. Để kiểm thử bằng unit-test trong trường hợp, chúng ta sẽ dùng ArgumentCaptor để theo dõi giá trị của Email object được truyền vào và verify giá trị các thuộc tính của nó.

Để theo dõi giá trị của email object được truyền vào chúng ta làm như sau

Mockito.verify(platform).send(emailCaptor.capture());

Để truy xuất giá trị của Email object đã truyền vào trước đó chúng ta sử dụng

Email emailCaptorValue = emailCaptor.getValue();

Kiểm thử ArgumentCaptor value

Sau khi hàm DeliveryPlatform#send() được thực thi, giá trị của tham số truyền vào sẽ được ghi lại, chúng ta có thể thực hiện việc kiểm tra tính đúng đắn của dữ liệu như sau

@ExtendWith(MockitoExtension.class)
public class EmailServiveTest {

    @Mock
    private DeliveryPlatform platform;

    @InjectMocks
    private EmailService emailService = new EmailService();

    @Captor
    private ArgumentCaptor<Email> emailCaptor;

    @Test
    public void whenDoesSupportHtml_expectHTMLEmailFormat() {
        String to = "[email protected]";
        String subject = "Using ArgumentCaptor";
        String body = "Hey, let'use ArgumentCaptor";

        emailService.send(to, subject, body, true);

        Mockito.verify(platform).send(emailCaptor.capture());
        Email value = emailCaptor.getValue();

        assertEquals(Format.HTML, value.getFormat());
        assertEquals(body, value.getBody());
        assertEquals(subject, value.getSubject());
        assertEquals(to, value.getAddress());
    }

}

ArgumentCaptor trong Static method

Ví dụ EmailService của chúng ta có thêm một method như sau

public class EmailService {
    // more code
    public void requestToDeft() {
        String url = "https://shareprogramming.net/";
        DeliveryPlatform.requestTo(url);
    }

}

Hàm requestToDeft() sử dụng static method DeliveryPlatform#requestTo() mà không trả về kết quả. Mockito cho phép chúng ta mock cả những static method thông qua mockito-line.

Để theo dõi dữ liệu được truyền vào static method chúng ta có thể làm MockedStatic.verify() như sau

 

@ExtendWith(MockitoExtension.class)
public class EmailServiveTest {

    @InjectMocks
    private EmailService emailService = new EmailService();

    @Captor
    private ArgumentCaptor<String> urlCaptor;

    @Test
    public void mockStaticMethodWithArgumentCaptor() {
        try (MockedStatic<DeliveryPlatform> mockedStatic = Mockito.mockStatic(DeliveryPlatform.class)) {
            emailService.requestToDeft();
            mockedStatic.verify(() -> {
                DeliveryPlatform.requestTo(urlCaptor.capture());
                assertEquals("https://shareprogramming.net/", urlCaptor.getValue());
            });
        }
    }

}

Tóm lược

Qua bài viết này chúng ta đã biết cách kiểm thử giá trị truyền các tham số truyền vào của các method thông qua ArgumentCaptor. Tính ngày rất hữu ích khi chúng ta muốn kiểm thử giá trị của các tham số đầu vào của một method.

Các bạn có thể tham khảo mã nguồn đầy đủ tại: argumentcaptor

Nguồn tham khảo

https://www.baeldung.com/mockito-argumentcaptor

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x