我在测试控制器时遇到问题,但我无法在简单的应用程序中重现该问题。当我运行该应用程序时,它运行良好。
我有一个控制器:
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
...