2

I'm having an issue testing a controller but I haven't been able to reproduce the problem in a simple application. When I run the app, it works fine.

I have a controller:

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

Notice that the @Postannotation is in the interface.

The problem with this controller is that the route POST /home is not being matched. I found that the problem is in AnnotatedMethodRouteBuilder#process(BeanDefinition<?> definition, ExecutableMethod<?, ?> method)---method does not have an HTTP mapping (i.e., ultimately @Post).

This is the output of the failing test:

    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

So, I created this test:

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

The method create has neither HttpMethodMapping nor UriMapping.

If I move the @Post annotation from the interface to the controller class, this test passes but other tests that send requests to POST /home fail with the following message:

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

This is my test config:

micronaut:
  server:
    port: -1
  security:
    basic-auth:
      enabled: true
    token:
      basic-auth:
        enabled: false
      jwt:
        enabled: false
...
Miguel Jiménez
  • 1,276
  • 1
  • 16
  • 24

0 Answers0