Làm thế nào để sử dụng ArgumentCaptor cho stubbing?


161

Trong tài liệu Mockito và javadocs, nó nói

Bạn nên sử dụng ArgumentCaptor với xác minh nhưng không được sử dụng.

nhưng tôi không hiểu làm thế nào ArgumentCaptor có thể được sử dụng để khai thác. Ai đó có thể giải thích tuyên bố trên và chỉ ra cách ArgumentCaptor có thể được sử dụng để khai thác hoặc cung cấp một liên kết cho thấy cách thực hiện?


1
Giải thích siêu ngắn & hay tại đây: dzone.com/articles/
Từ

Câu trả lời:


271

Giả sử phương pháp sau để kiểm tra:

public boolean doSomething(SomeClass arg);

Tài liệu Mockito nói rằng bạn không nên sử dụng captor theo cách này:

when(someObject.doSomething(argumentCaptor.capture())).thenReturn(true);
assertThat(argumentCaptor.getValue(), equalTo(expected));

Bởi vì bạn chỉ có thể sử dụng diêm trong quá trình khai thác:

when(someObject.doSomething(eq(expected))).thenReturn(true);

Nhưng xác minh là một câu chuyện khác nhau. Nếu thử nghiệm của bạn cần đảm bảo rằng phương thức này được gọi với một đối số cụ thể, hãy sử dụng ArgumentCaptorvà đây là trường hợp được thiết kế:

ArgumentCaptor<SomeClass> argumentCaptor = ArgumentCaptor.forClass(SomeClass.class);
verify(someObject).doSomething(argumentCaptor.capture());
assertThat(argumentCaptor.getValue(), equalTo(expected));

Cảm ơn câu trả lời. Tôi có một câu hỏi. Trong khối mã thứ ba, chúng ta biết rằng true chỉ được trả về khi dự kiến được truyền cho doS Something. Nhưng khi nào được trả về đúng trong khối mã thứ hai? Hay someObject luôn trả về true cho someMethod trong trường hợp đó?
Không thể nói

Hừm, tôi tin bạn có nghĩa là "Nhưng khi nào thì trả lại đúng trong khối mã thứ ba ?". Trong khối mã thứ ba, chúng tôi không quan tâm đến giá trị trả về và để nó là giá trị mặc định. Đối với boolean nó là false, không true.
Rorick

Không, tôi tính tất cả các khối nền màu xám là các khối mã. Bao gồm một lớp lót đầu tiên. Tôi đã đề cập đến dòng khi (someObject.doSthing (argumentCaptor.capture ())). ThenReturn (true);
Không thể nói

Ồ xin lỗi. Có, trong trường hợp này đúng sẽ luôn được trả lại.
Rorick

3
không chắc chắn lý do để "không sử dụng với stubbing" là một lý do đơn giản. các đối sánh không cung cấp cho chúng tôi đối số dự kiến ​​thực tế (chỉ là loại) và dẫn đến việc ổn với các thử nghiệm vượt qua mặc dù các đối số có thể sai.
dtc

0

Dòng

when(someObject.doSomething(argumentCaptor.capture())).thenReturn(true);

sẽ làm tương tự như

when(someObject.doSomething(Matchers.any())).thenReturn(true);

Vì vậy, sử dụng argumentCaptor.capture () khi khai thác không có giá trị gia tăng. Sử dụng Matchers.any () cho thấy tốt hơn những gì thực sự xảy ra và do đó tốt hơn cho khả năng đọc. Với argumentCaptor.capture (), bạn không thể đọc những đối số nào thực sự phù hợp. Và thay vì sử dụng bất kỳ (), bạn có thể sử dụng các công cụ đối sánh cụ thể hơn khi bạn có thêm thông tin (lớp của đối số dự kiến), để cải thiện bài kiểm tra của bạn.

Và một vấn đề khác: Nếu sử dụng argumentCaptor.capture () khi khai thác, nó sẽ không rõ có bao nhiêu giá trị mà bạn sẽ mong đợi được ghi lại sau khi xác minh. Chúng tôi muốn nắm bắt một giá trị trong quá trình xác minh, không phải trong quá trình khai thác vì tại thời điểm đó vẫn chưa có giá trị để nắm bắt. Vì vậy, những người nắm bắt đối số nắm bắt phương thức nắm bắt trong quá trình khai thác là gì? hay nó không bắt được gì? Tôi không có câu trả lời cho câu hỏi này. Tôi coi đó là hành vi không xác định và tôi không muốn sử dụng hành vi không xác định.


0

Theo giả thuyết, nếu tìm kiếm đưa bạn đến câu hỏi này thì có lẽ bạn muốn điều này:

doReturn(someReturn).when(someObject).doSomething(argThat(argument -> argument.getName().equals("Bob")));

Tại sao? Bởi vì giống như tôi, bạn coi trọng thời gian và bạn sẽ không thực hiện .equalschỉ vì kịch bản thử nghiệm duy nhất.

Và 99% các bài kiểm tra rơi ra với null được trả về từ Mock và trong một thiết kế hợp lý, bạn sẽ tránh được việc trả lại nullbằng mọi giá, sử dụng Optionalhoặc chuyển sang Kotlin. Điều này ngụ ý rằng verifykhông cần phải sử dụng thường xuyên và ArgumentCaptors chỉ quá tẻ nhạt để viết.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.