2

我在测试控制器时遇到问题,但我无法在简单的应用程序中重现该问题。当我运行该应用程序时,它运行良好。

我有一个控制器:

public interface HomeOperations {
    @Post // Micronaut's Post
    HttpResponse<TheResponse> create(@NotNull @Valid @Body TheCommand command);
}

@Controller("/home")
@Secured("user")
@RequiredArgsConstructor // lombok
@Validated
public class HomeController implements HomeOperations {
    @Override
    @SneakyThrows // lombok
    @ExecuteOn(TaskExecutors.IO)
    public HttpResponse<TheResponse> create(@NotNull @Valid @Body TheCommand command) {
        return HttpResponse.ok(...);
    }
}

请注意,@Post注释在界面中。

这个控制器的问题是路由POST /home不匹配。我发现问题出在AnnotatedMethodRouteBuilder#process(BeanDefinition<?> definition, ExecutableMethod<?, ?> method)---method没有 HTTP 映射(即,最终@Post)。

这是失败测试的输出:

    12:51:39.828 [nioEventLoopGroup-1-4] DEBUG DefaultTokenResolver - Request POST, /home, no token found.
    12:51:39.833 [nioEventLoopGroup-1-4] DEBUG Authenticator - com.example.controllers.DummyAuthenticationProvider
    12:51:39.835 [nioEventLoopGroup-1-4] INFO  DummyAuthenticationProvider - Successful dummy login [user]
    12:51:39.904 [nioEventLoopGroup-1-4] DEBUG SecurityFilter - Attributes: roles=>[user], username=>880f1a24-4997-40a6-bbf1-dde1f3871451
    12:51:39.905 [nioEventLoopGroup-1-4] DEBUG InterceptUrlMapRule - One or more of the IP patterns matched the host address [127.0.0.1]. Continuing request processing.
    12:51:39.908 [nioEventLoopGroup-1-4] DEBUG InterceptUrlMapRule - No url map pattern exact match found for path [/home] and method [POST]. Searching in patterns with no defined method.
    12:51:39.909 [nioEventLoopGroup-1-4] DEBUG InterceptUrlMapRule - No url map pattern match found for path [/home]. Returning unknown.
    12:51:39.910 [nioEventLoopGroup-1-4] DEBUG SecurityFilter - Authorized request POST /home. No rule provider authorized or rejected the request.

ControllerServerTest > testRegisterEntity() FAILED
    io.micronaut.http.client.exceptions.HttpClientResponseException: Forbidden

所以,我创建了这个测试:

    // Receives HomeController.class as parameter
    void testController(final Class<?> type) {
        final BeanDefinition<?> definition =
            this.context.getBeanDefinition(type);
        Assertions.assertNotNull(
            definition.getAnnotation(Controller.class),
            "Controller annotation is null"
        );
        definition.getExecutableMethods()
            .forEach(method -> {
                if (!method.hasStereotype(Executable.class)) {
                    return;
                }
                // These two are failing:
                final Optional<Class<? extends Annotation>> http =
                    method.getAnnotationTypeByStereotype(HttpMethodMapping.class);
                final Optional<Class<? extends Annotation>> uri =
                    method.getAnnotationTypeByStereotype(UriMapping.class);
                Assertions.assertTrue(
                    http.isPresent(),
                    String.format("Missing method mapping for method %s", method)
                );
                Assertions.assertTrue(
                    uri.isPresent(),
                    String.format("Missing URI mapping for method %s", method)
                );
            });
    }

该方法create既没有HttpMethodMapping也没有UriMapping

如果我将@Post注释从接口移动到控制器类,则此测试通过,但发送请求的其他测试POST /home失败并显示以下消息:

More than 1 route matched the incoming request. The following routes matched /home: POST - /home, POST - /home
io.micronaut.http.client.exceptions.HttpClientResponseException: More than 1 route matched the incoming request. The following routes matched /home: POST - /home, POST - /home

这是我的测试配置:

micronaut:
  server:
    port: -1
  security:
    basic-auth:
      enabled: true
    token:
      basic-auth:
        enabled: false
      jwt:
        enabled: false
...
4

0 回答 0