我正在开发一个使用功能端点开发的Spring boot2应用程序。路由器附带了一些过滤器(HandlerFilterFunction<ServerResponse, ServerResponse>
的实现)。我正试图测试我遇到的问题,并提出这个问题。
使用框架
过滤我要测试的内容
public class ResourceParsingFilter implements HandlerFilterFunction<ServerResponse, ServerResponse> {
/**
* {@inheritDoc}
*/
@Override
public Mono<ServerResponse> filter(ServerRequest request, HandlerFunction<ServerResponse> next) {
final HttpMethod httpMethod = request.method();
final String requestPath = request.path();
// Collect the resource id and type from path
final ResourceDetail resourceDetail = WebUtilsFunctions.FN_GET_RESOURCE_DETAIL_FROM_PATH.apply(requestPath);
switch (httpMethod) {
case GET:
if (!request.queryParam("q").isPresent() && StringUtils.isBlank(resourceDetail.getResourceId())) {
return Mono.error(
new AppException(Exceptions.APP_400002.exceptionCode(),
WebUtilsFunctions.FN_FORMAT_STRING.apply(Exceptions.APP_400002.exceptionMessage(), new String[] {httpMethod.name()})));
}
break;
case PUT:
case DELETE:
if (StringUtils.isBlank(resourceDetail.getResourceId())) {
return Mono.error(
new AppException(Exceptions.APP_400002.exceptionCode(),
WebUtilsFunctions.FN_FORMAT_STRING.apply(Exceptions.APP_400002.exceptionMessage(), new String[] {httpMethod.name()})));
}
break;
default:
break;
}
// Store resourceDetail in request
request.attributes().put("RESOURCE_DETAIL", resourceDetail);
return next.handle(request);
}
}
模拟应用配置以测试过滤器
@Configuration
@EnableWebFlux
public class MockAppConfig {
@Bean
public ResourceParsingFilter resourceParsingFilterBean() {
return new ResourceParsingFilter();
}
@Bean // This is my own custom exception handler implementation
public GlobalExceptionHandler globalExceptionHandler(final ApplicationContext applicationContext,
final ServerCodecConfigurer serverCodecConfigurer) {
return new GlobalExceptionHandler(applicationContext, serverCodecConfigurer);
}
}
模拟路由器配置(我根据Spring Boot团队在其gitter频道(https://github.com/spring-projects/spring-boot/issues/6602)中的建议单独创建了这个类
@Configuration
public class MockResourceParsingRouterConfig {
@Autowired
private ResourceParsingFilter resourceParsingFilter;
@Bean("resourceParsingFilterRoutes")
public RouterFunction<ServerResponse> resourceParsingFilterRoutes() {
// Dummy route configuration for testing ResourceParsingFilter
return RouterFunctions.route(RequestPredicates.GET("/resourceParsing/{id}"), req -> ServerResponse.ok().build())
.andRoute(RequestPredicates.PUT("/resourceParsing/{id}"), req -> ServerResponse.ok().build())
.andRoute(RequestPredicates.DELETE("/resourceParsing/{id}"), req -> ServerResponse.ok().build())
.andRoute(RequestPredicates.GET("/resourceParsing/"), req -> ServerResponse.ok().build()) // GET Search URL
.filter(resourceParsingFilter);
}
}
测试类
@Test(groups = "resourceParsingFilterTests")
@WebFluxTest
@Import({MockAppConfig.class, MockResourceParsingRouterConfig.class})
public class ResourceParsingFilterTest extends AbstractTestNGSpringContextTests {
@Autowired
private WebTestClient webTestClient;
// ====== Passing tests
@Test
public void get_withoutId() {
webTestClient.get().uri("/resourceParsing/")
.exchange() // Fire http request
.expectStatus() // Assert on HTTP Status
.isBadRequest()
;
}
@Test(dependsOnMethods = {"get_withoutId"})
public void get_withoutId_searchQueryParamPresent() {
webTestClient.get().uri("/resourceParsing/?q=id:345")
.exchange() // Fire http request
.expectStatus() // Assert on HTTP Status
.isOk()
;
}
// ====== Failing tests
@Test(dependsOnMethods = {"get_withoutId_searchQueryParamPresent"})
public void put_withoutId() {
webTestClient.put().uri("/resourceParsing/")
.exchange() // Fire http request
.expectStatus() // Assert on HTTP Status
.isBadRequest()
;
}
}
测试put_withoutId
失败,因为(模拟)服务器正在抛出404
而不是预期400
。
请检查GitHub repo https://github.com/nnanda2016/router-fn-demo以获取完整代码(如果您愿意),这是一个与我的真实应用程序在同一行的演示应用程序(由于客户机密性合规性,我无法共享真实代码)。
有人可以就如何解决这个问题给我一些指示吗?
答案 0 :(得分:1)
@WebFluxTest
注释不支持RouterFunction
的测试,只支持WebFlux注释控制器的测试。
@WebFluxTest
和@WebMvcTest
是关于将单个带注释的控制器测试为没有完整Web基础结构的Web组件。 RouterFunction
通常依赖于多个处理程序来定义实际的函数 - 所以我们不能在没有对路由进行硬性假设的情况下一致地测试单个处理程序,或者要求开发人员设计他们的架构以拥有多个RouterFunction
bean。
这将更好地记录once this Spring Boot issue is resolved。
与此同时,您可能应该使用@SpringBootTest
;如果您不要求特定端口,此集成将配置完整的Web堆栈,但不会启动任何服务器。