当我同步时,我编写了单元测试来模拟持久性部分并检查调用者的行为。这是一个关于我通常做的事情的例子:
@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?
答案 0 :(得分:1)
通常,我会使用评论来发布此内容,但是格式会丢失。公认的解决方案效果很好,只需注意,可以使用Java 8+对其进行一些简化,并且可以使用实际的对象而不是JSON。
doAnswer((Answer<AsyncResult<List<Show>>>) arguments -> {
((Handler<AsyncResult<List<Show>>>) arguments.getArgument(1)).handle(asyncResult);
return null;
}).when(showService).findShowsByShowFilter(any(), any());
getArgument(1),引用诸如以下方法的处理程序参数的索引:
@Fluent
@Nonnull
ShowService findShowsByShowFilter(@Nonnull final ShowFilter showFilter,
@Nonnull final Handler<AsyncResult<List<Show>>> resultHandler);