当我进行同步操作时,我会编写单元测试来模拟持久化部分并检查调用者的行为。以下是我通常所做的一个示例:
@Mock
private OfferPersistenceServiceImpl persistenceService;
@Inject
@InjectMocks
private OfferServiceImpl offerService;
...
@Test
public void createInvalidOffer() {
offer = new Offer(null, null, null, null, null, 4, 200D, 90D);
String expectedMessage = Offer.class.getName() + " is not valid: " + offer.toString();
Mockito.when(persistenceService.create(offer)).thenThrow(new IllegalArgumentException(expectedMessage));
Response response = offerService.create(offer);
Mockito.verify(persistenceService, Mockito.times(1)).create(offer);
Assert.assertEquals(INVALID_INPUT, response.getStatus());
String actualMessage = response.getEntity().toString();
Assert.assertEquals(expectedMessage, actualMessage);
}
但现在我爱上了Vertx.io(我对它还很陌生),我想使用异步方式。不错。但是Vertx有处理器,因此模拟新的持久性组件如下:
...
mongoClient.insert(COLLECTION, offer, h-> {
...
});
我猜测如何模拟处理程序
h
来测试使用该 mongoClient
的类,甚至是否正确地使用 Vertx.io 进行测试。我正在使用 vertx.io 3.5.0
、junit 4.12
和 mockito 2.13.0
。谢谢。更新: 我试图按照 tsegimond 的建议进行操作,但我不知道 Mockito 的
Answer
和 ArgumentCaptor
如何帮助我。以下是我迄今为止尝试过的内容。
使用 ArgumentCaptor
:JsonObject offer = Mockito.mock(JsonObject.class);
Mockito.when(msg.body()).thenReturn(offer);
Mockito.doNothing().when(offerMongo).validate(offer);
RuntimeException rex = new RuntimeException("some message");
...
ArgumentCaptor<Handler<AsyncResult<String>>> handlerCaptor =
ArgumentCaptor.forClass(Handler.class);
ArgumentCaptor<AsyncResult<String>> asyncResultCaptor =
ArgumentCaptor.forClass(AsyncResult.class);
offerMongo.create(msg);
Mockito.verify(mongoClient,
Mockito.times(1)).insert(Mockito.anyString(), Mockito.any(), handlerCaptor.capture());
Mockito.verify(handlerCaptor.getValue(),
Mockito.times(1)).handle(asyncResultCaptor.capture());
Mockito.when(asyncResultCaptor.getValue().succeeded()).thenReturn(false);
Mockito.when(asyncResultCaptor.getValue().cause()).thenReturn(rex);
Assert.assertEquals(Json.encode(rex), msg.body().encode());
并使用 Answer
:
ArgumentCaptor<AsyncResult<String>> handlerCaptor =
ArgumentCaptor.forClass(AsyncResult.class);
AsyncResult<String> result = Mockito.mock(AsyncResult.class);
Mockito.when(result.succeeded()).thenReturn(true);
Mockito.when(result.cause()).thenReturn(rex);
Mockito.doAnswer(new Answer<MongoClient>() {
@Override
public MongoClient answer(InvocationOnMock invocation) throws Throwable {
((Handler<AsyncResult<String>>)
invocation.getArguments()[2]).handle(handlerCaptor.capture());
return null;
}
}).when(mongoClient).insert(Mockito.anyString(), Mockito.any(),
Mockito.any());
userMongo.create(msg);
Assert.assertEquals(Json.encode(rex), msg.body().encode());
现在我有些困惑了。是否有一种方法来模拟AsyncResult
,以便让它在succeed()
上返回false?