Java Spring Boot2功能终结点WebFluxTest与ID为({ID})的URL的PUT和DELETE不匹配

Java Spring Boot2功能终结点WebFluxTest与ID为({ID})的URL的PUT和DELETE不匹配,java,spring,spring-boot,spring-webflux,spring-boot-test,Java,Spring,Spring Boot,Spring Webflux,Spring Boot Test,我正在开发一个SpringBoot2应用程序,它是用功能端点开发的。路由器附带一些过滤器(实现HandlerFilterFunction)。我试着测试我被卡住的飞片,并问这个问题 使用的框架 弹簧靴2.0.0.0版本 TestNG 我正在尝试测试的过滤器 public class ResourceParsingFilter implements HandlerFilterFunction<ServerResponse, ServerResponse> { /**

我正在开发一个SpringBoot2应用程序,它是用功能端点开发的。路由器附带一些过滤器(实现
HandlerFilterFunction
)。我试着测试我被卡住的飞片,并问这个问题

使用的框架

  • 弹簧靴2.0.0.0版本
  • TestNG
我正在尝试测试的过滤器

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

}
模拟路由器配置(我根据Spring Boot团队在gitter频道()中的建议单独创建了这个类)

测试
put_without id
失败,因为(模拟)服务器正在抛出
404
,而不是预期的
400

请检查GitHub repo以获取完整的代码(如果您愿意),这是一个与我的真实应用程序位于同一行的演示应用程序(由于符合客户机密性,我无法共享真实代码)


有人能给我一些关于如何解决这个问题的建议吗?

WebFluxTest注释不支持测试
路由函数,只支持WebFlux注释的控制器

@WebFluxTest
@WebMvcTest
是关于在没有完整web基础设施的情况下将单个带注释的控制器作为web组件进行测试。
RouterFunction
通常依赖于多个处理程序来定义实际功能-因此,如果不对ro进行硬假设,我们无法一致地测试单个处理程序使用或要求开发人员设计他们的体系结构,使其具有多个
RouterFunction
bean

这将得到更好的记录

同时,您可能应该使用
@springbootest
来实现此目的;如果您不要求特定的端口,此集成将配置完整的web堆栈,但不会启动任何服务器

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