英文:
How Do I Unit Test Micronaut Error Handlers?
问题
以下是您要翻译的代码部分:
有两种方法在我的Controller中,POST控制器:
@Post
HttpResponse<Publisher<ControllerResponseModel>> post(@Body String designJson) throws JsonProcessingException {
Publisher<ControllerResponseModel> response = designService.save(designJson);
return HttpResponse.created(response);
}
... 以及如果JSON格式错误时的错误处理程序:
@Error(exception = JsonProcessingException.class)
HttpResponse<Publisher<ErrorModel>> jsonProcessingException(HttpRequest request, JsonProcessingException exception) {
return HttpResponse.badRequest(Mono.just(new ErrorModel(exception.getMessage())));
}
希望这对您有所帮助。
英文:
There are two methods in my Controller, the POST controller:
@Post
HttpResponse<Publisher<ControllerResponseModel>> post(@Body String designJson) throws JsonProcessingException {
Publisher<ControllerResponseModel> response = designService.save(designJson);
return HttpResponse.created(response);
}
... and the Error handler if the JSON is malformed:
@Error(exception = JsonProcessingException.class)
HttpResponse<Publisher<ErrorModel>> jsonProcessingException(HttpRequest request, JsonProcessingException exception) {
return HttpResponse.badRequest(Mono.just(new ErrorModel(exception.getMessage())));
}
When I run the application, everything works as intended. A response of ErrorModel is shown for malformed JSON; a response of the proper type for properly formed JSON.
But I can't seem to unit test the error handlers in the Controller.
My hope was something like this would work. I mock out the service and have it throw the proper exception. But when it's run, the thrown exception fails the test and the response object isn't populated or asserted against.
@Test
void post_malformedJson() throws IOException {
final String jsonData = "var: 37";
final JsonParser parser = JsonFactory.builder().build().createParser(jsonData);
doThrow(new JsonParseException(parser, "")).when(designService).save(anyString());
HttpResponse<Publisher<ControllerResponseModel>> response = instance.post(jsonData);
assertThat(response.getBody().isPresent()).isTrue();
StepVerifier.create(response.getBody().get())
.expectNext(new ErrorModel("SOMETHING"))
.expectComplete()
.verify();
}
Any tips (even if it's a completely different structure than above) on how to unit test Micronaut Error handlers?
答案1
得分: 1
以下是您要翻译的内容:
"Looking at the test, I would guess you are instantiating the resource class yourself. As you can see, the controlled doesn't actually call the handler anywhere. It is used by Micronaut to create a proxy that catches the specified exception and handles it as defined in the handler.
To make this work you need more than just the controller instance. That's what the @MicronautTest
annotation is for. It starts up your application, including the error handlers.
Test itself is similar to what you have. Mock design service to skip business logic and simulate the error. The main difference is that you need to invoke the operation through your endpoint since it's running. Here I am using rest-assured to send the POST request.
@MicronautTest
class DemoTest {
@Inject
DesignService designService;
@MockBean(DesignService.class)
DesignService designService() {
return Mockito.mock(DesignService.class);
}
@Test
public void testHelloEndpoint(RequestSpecification spec) throws JsonProcessingException {
final String expectedMessage = "my message";
final String malformedBody = "var: 37";
Mockito when(this.designService.save(ArgumentMatchers.anyString()))
.thenThrow(new MyParsingException(expectedMessage));
String error = spec
.given().body(malformedBody).contentType(ContentType.TEXT)
.when().post("/hello")
.then()
.statusCode(400)
// Can also use .as(ErrorModel.class) and assert on that
.extract().body().asString();
assertTrue(error.contains(expectedMessage));
}
class MyParsingException extends JsonProcessingException {
public MyParsingException(String msg) {
super(msg);
}
}
}"
英文:
Looking at the test, I would guess you are instantiating the resource class yourself. As you can see, the controlled doesn't actually call the handler anywhere. It is used by Micronaut to create a proxy that catches the specified exception and handles it as defined in the handler.
To make this work you need more than just the controller instance. That's what the @MicronautTest
annotation is for. It starts up your application, including the error handlers.
Test itself is similar to what you have. Mock design service to skip business logic and simulate the error. The main difference is that you need to invoke the operation through your endpoint since it's running. Here I am using rest-assured to send the POST request.
@MicronautTest
class DemoTest {
@Inject
DesignService designService;
@MockBean(DesignService.class)
DesignService designService() {
return Mockito.mock(DesignService.class);
}
@Test
public void testHelloEndpoint(RequestSpecification spec) throws JsonProcessingException {
final String expectedMessage = "my message";
final String malformedBody = "var: 37";
Mockito.when(this.designService.save(ArgumentMatchers.anyString()))
.thenThrow(new MyParsingException(expectedMessage));
String error = spec
.given().body(malformedBody).contentType(ContentType.TEXT)
.when().post("/hello")
.then()
.statusCode(400)
// Can also use .as(ErrorModel.class) and assert on that
.extract().body().asString();
assertTrue(error.contains(expectedMessage));
}
class MyParsingException extends JsonProcessingException {
public MyParsingException(String msg) {
super(msg);
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论