2017-12-21 30 views
0

내가 동기화 할 때 단위 테스트를 작성하여 지속성 부분을 조롱하고 호출자의 동작을 확인합니다. 여기에 내가 일반적으로 무엇을했는지에 대한 예입니다Vertx.io 비동기 처리기를 조롱

@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 (이에 나는 아주 새로운 오전)와 사랑에 빠졌다 내가 비동기되고 싶어요. 좋은. 그래서

... 
mongoClient.insert(COLLECTION, offer, h-> { 
    ... 
}); 

내가 그 mongoClient 심지어는 함께 테스트하는 올바른 방법 인 경우를 사용하고 테스트 클래스 처리기 h을 조롱하는 방법을 추측하고있다 : 그러나 Vertx 핸들러 때문에,이 같은 모의 외모에 새 지속성 구성 요소가 Vertx.io. vertx.io 3.5.0, junit 4.12mockito 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

https://fernandocejas.com/2014/04/08/unit-testing-asynchronous-methods-with-mockito/ – tsegismont

답변

0

마지막으로 조사 할 시간이 있었는데 만들었습니다. 여기 내 해결책이있다. 당신이 때 모의 verticle 시작해야합니다 있도록

@RunWith(PowerMockRunner.class) 
@PowerMockRunnerDelegate(VertxUnitRunner.class) 
@PrepareForTest({ MongoClient.class }) 
public class PersistenceTest { 

private MongoClient mongo; 
private Vertx vertx; 

@Before 
public void initSingleTest(TestContext ctx) throws Exception { 
    vertx = Vertx.vertx(); 
    mongo = Mockito.mock(MongoClient.class); 
    PowerMockito.mockStatic(MongoClient.class); 
    PowerMockito.when(MongoClient.createShared(Mockito.any(), Mockito.any())).thenReturn(mongo); 
    vertx.deployVerticle(Persistence.class, new DeploymentOptions(), ctx.asyncAssertSuccess()); 
} 

@SuppressWarnings("unchecked") 
@Test 
public void loadSomeDocs(TestContext ctx) { 
    Doc expected = new Doc(); 
    expected.setName("report"); 
    expected.setPreview("loremipsum"); 
    Message<JsonObject> msg = Mockito.mock(Message.class); 
    Mockito.when(msg.body()).thenReturn(JsonObject.mapFrom(expected)); 
    JsonObject result = new JsonObject().put("name", "report").put("preview", "loremipsum"); 
    AsyncResult<JsonObject> asyncResult = Mockito.mock(AsyncResult.class); 
    Mockito.when(asyncResult.succeeded()).thenReturn(true); 
    Mockito.when(asyncResult.result()).thenReturn(result); 
    Mockito.doAnswer(new Answer<AsyncResult<JsonObject>>() { 
    @Override 
    public AsyncResult<JsonObject> answer(InvocationOnMock arg0) throws Throwable { 
    ((Handler<AsyncResult<JsonObject>>) arg0.getArgument(3)).handle(asyncResult); 
    return null; 
    } 
    }).when(mongo).findOne(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any()); 
    Async async = ctx.async(); 
    vertx.eventBus().send("persistence", new JsonObject(), msgh -> { 
    if (msgh.failed()) { 
    System.out.println(msgh.cause().getMessage()); 
    } 
    ctx.assertTrue(msgh.succeeded()); 
    ctx.assertEquals(expected, Json.decodeValue(msgh.result().body().toString(), Doc.class)); 
    async.complete(); 
    }); 
    async.await(); 
    } 
} 

사용 Powemockito

MongoClient.createShared 정적 메서드를 조롱합니다. 조롱 비동기 처리기는 작성할 코드의 비트입니다. 당신이 볼 수 있듯이 Message<JsonObject> msg = Mockito.mock(Message.class);에서 시작하여 Mockito.doAnswer(new Answer...에서 끝납니다. Answer의 메소드에서 처리기 param을 선택하고 비동기 결과를 처리하도록 강제 실행하면 완료됩니다.