如何单元测试Micronaut错误处理程序?

huangapple go评论53阅读模式
英文:

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);
        }
    }

}

huangapple
  • 本文由 发表于 2023年4月10日 23:47:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/75978561.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定