Tôi đang sử dụng Mockito để thử nghiệm đơn vị dịch vụ sau này. Tôi bối rối khi sử dụng doAnswer
vs thenReturn
.
Bất cứ ai có thể giúp tôi một cách chi tiết? Cho đến nay, tôi đã thử nó với thenReturn
.
Tôi đang sử dụng Mockito để thử nghiệm đơn vị dịch vụ sau này. Tôi bối rối khi sử dụng doAnswer
vs thenReturn
.
Bất cứ ai có thể giúp tôi một cách chi tiết? Cho đến nay, tôi đã thử nó với thenReturn
.
Câu trả lời:
Bạn nên sử dụng thenReturn
hoặc doReturn
khi bạn biết giá trị trả về tại thời điểm bạn mô phỏng một cuộc gọi phương thức. Giá trị đã xác định này được trả về khi bạn gọi phương thức bị chế nhạo.
thenReturn(T value)
Đặt một giá trị trả về sẽ được trả về khi phương thức được gọi.
@Test
public void test_return() throws Exception {
Dummy dummy = mock(Dummy.class);
int returnValue = 5;
// choose your preferred way
when(dummy.stringLength("dummy")).thenReturn(returnValue);
doReturn(returnValue).when(dummy).stringLength("dummy");
}
Answer
được sử dụng khi bạn cần thực hiện các hành động bổ sung khi một phương thức giả được gọi, ví dụ: khi bạn cần tính toán giá trị trả về dựa trên các tham số của lệnh gọi phương thức này.
Sử dụng
doAnswer()
khi bạn muốn khai báo một phương thức void với genericAnswer
.Câu trả lời chỉ định một hành động được thực thi và một giá trị trả về được trả về khi bạn tương tác với mô hình.
@Test
public void test_answer() throws Exception {
Dummy dummy = mock(Dummy.class);
Answer<Integer> answer = new Answer<Integer>() {
public Integer answer(InvocationOnMock invocation) throws Throwable {
String string = invocation.getArgumentAt(0, String.class);
return string.length() * 2;
}
};
// choose your preferred way
when(dummy.stringLength("dummy")).thenAnswer(answer);
doAnswer(answer).when(dummy).stringLength("dummy");
}
Answer
chỉ với return UUID.randomUUID();
.
Answer
là một giao diện chức năng, vì vậy với Java 8, bạn có thể thay thế nó bằng một biểu thức lambda. Nếu không đủ sạch sẽ có thể tái cấu trúc bất thường và bình thường khác.
doAnswer
và thenReturn
làm điều tương tự nếu:
Hãy chế nhạo BookService này
public interface BookService {
String getAuthor();
void queryBookTitle(BookServiceCallback callback);
}
Bạn có thể khai thác getAuthor () bằng cách sử dụng doAnswer
và thenReturn
.
BookService service = mock(BookService.class);
when(service.getAuthor()).thenReturn("Joshua");
// or..
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return "Joshua";
}
}).when(service).getAuthor();
Lưu ý rằng khi sử dụng doAnswer
, bạn không thể chuyển một phương thức vào when
.
// Will throw UnfinishedStubbingException
doAnswer(invocation -> "Joshua").when(service.getAuthor());
Vì vậy, khi nào bạn sẽ sử dụng doAnswer
thay vì thenReturn
? Tôi có thể nghĩ đến hai trường hợp sử dụng:
Sử dụng doAnswer, bạn có thể thực hiện một số hành động bổ sung khi gọi phương thức. Ví dụ: kích hoạt một cuộc gọi lại trên queryBookTitle.
BookServiceCallback callback = new BookServiceCallback() {
@Override
public void onSuccess(String bookTitle) {
assertEquals("Effective Java", bookTitle);
}
};
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
BookServiceCallback callback = (BookServiceCallback) invocation.getArguments()[0];
callback.onSuccess("Effective Java");
// return null because queryBookTitle is void
return null;
}
}).when(service).queryBookTitle(callback);
service.queryBookTitle(callback);
Khi sử dụng when-thenReturn trên Spy Mockito sẽ gọi phương thức thực và sau đó khai ra câu trả lời của bạn. Điều này có thể gây ra sự cố nếu bạn không muốn gọi phương thức thực, như trong mẫu này:
List list = new LinkedList();
List spy = spy(list);
// Will throw java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
when(spy.get(0)).thenReturn("java");
assertEquals("java", spy.get(0));
Sử dụng doAnswer chúng ta có thể khai thác nó một cách an toàn.
List list = new LinkedList();
List spy = spy(list);
doAnswer(invocation -> "java").when(spy).get(0);
assertEquals("java", spy.get(0));
Trên thực tế, nếu bạn không muốn thực hiện các hành động bổ sung khi gọi phương thức, bạn có thể sử dụng doReturn
.
List list = new LinkedList();
List spy = spy(list);
doReturn("java").when(spy).get(0);
assertEquals("java", spy.get(0));
doAnswer(new Answer() { ... return null;}
tôi nhận được cảnh báo trong eclipse cho "Câu trả lời là kiểu thô. Tham chiếu đến kiểu chung Câu trả lời <T> nên được tham số hóa". Có cách nào để giải quyết điều này (ngoại trừ việc bỏ qua cảnh báo của c) không?
code = UUID.randomUUID()
tôi thấy không thể thực hiện điều này vớimockito
.