spring 云网关自定义过滤器端到端测试如何进行?

How do I spring cloud gateway custom filter e2e test?

我已经实现了自定义 GatewayFilterFactory 过滤器。但我不知道如何使用 e2e 设置测试此过滤器。

我参考了 official spring-cloud-gateway AddRequestHeaderGatewayFilterFactoryTests test case code.


这是我的自定义过滤器代码:

@Component
public class MyCustomFilter implements GatewayFilterFactory<MyCustomFilter.Config>, Ordered {

    @Override
    public GatewayFilter apply(Config config) {
        return new OrderedGatewayFilter((this::filter), getOrder());
    }

    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        /* do some filtering */
    }


    @Override
    public int getOrder() {
        return 1000;
    }

    @Override
    public Config newConfig() {
        return new Config(MyCustomFilter.class.getSimpleName());
    }

    public static getConfig() {
        return 
    }

    @Getter
    @Setter
    public static class Config {
        private String name;

        Config(String name) {
            this.name = name;
        }
    }
}

这是我的测试代码:

BaseWebClientTests class 看起来和 official BaseWebClientTests class code

完全一样
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
@DirtiesContext
@ActiveProfiles("my-custom-filter")
public class MyCustomFilterTests extends BaseWebClientTests {
    @LocalServerPort
    protected int port = 0;

    protected WebTestClient testClient;

    protected WebClient webClient;

    protected String baseUri;

    @Before
    public void setup() throws Exception {
        setup(new ReactorClientHttpConnector(), "http://localhost:" + port);
    }

    protected void setup(ClientHttpConnector httpConnector, String baseUri) {
        this.baseUri = baseUri;
        this.webClient = WebClient.builder().clientConnector(httpConnector)
                .baseUrl(this.baseUri).build();
        this.testClient = WebTestClient
                .bindToServer(httpConnector)
                .baseUrl(this.baseUri)
                .build();
    }

    @Test
    public void shouldFailByFilterTests() {
        /* This test should be failed but success :( */
        testClient.get().uri("/api/path")
                .exchange().expectBody(Map.class).consumeWith(result -> {
            /* do assertion */
        });
    }

    @EnableAutoConfiguration
    @SpringBootConfiguration
    @Import(DefaultTestConfig.class)
    public static class TestConfig {

        @Value("${test.uri}")
        String uri;

        @Bean
        public MyCustomFilter myCustomFilter() {
            return new MyCustomFilter();
        }

        @Bean
        public RouteLocator testRouteLocator(RouteLocatorBuilder builder, MyCustomFilter myCustomFilter) {
            return builder.routes().route("my_custom_filter",
                    r -> r.path("/api/path")
                            .filters(f -> f.filter(myCustomFilter.apply(new MyCustomFilter.Config("STRING"))))
                            .uri(uri))
                    .build();
        }

    }
}

最后的目标控制器如下所示:

@RestController
@RequestMapping("/api/path")
public class HttpBinCompatibleController {

    @GetMapping("/")
    public Mono<BodyData> identity() {
        return Mono.just(new BodyData("api success"));
    }

    @NoArgsConstructor
    @AllArgsConstructor
    @Getter
    static class BodyData {
        private String message;
    }
}

我理解这个过滤器工厂测试代码是如何工作的

testClient 发送请求,自定义应该做一些过滤,然后目标控制器应该从 testClient.

接收请求

我对这个 shouldFailByFilterTests TC 的期望是,在 testClient 的请求发送到目标控制器之前,该请求应该被 MyCustomFilter 拒绝。 但是请求发送到目标控制器。

我认为来自 testClient 的请求未被 testRouteLocator 代理,但我不确定

问题

  1. 这个问题的原因是什么?
  2. 还有其他方法可以测试我自己的自定义过滤器吗?

此问题与 Spring 引导和 Spring 云之间的版本不兼容有关。

我使用的是 Spring 引导版本 2.1.7 和 Spring 云版本 Greenwich.SR2。

然后我在这个link

上找到了这个'Release train Spring Boot compatibility'table

在我注意到版本不兼容之前,为了使用 @Configuration(proxyBeanMethods = false) 功能,将 Spring 引导版本升级到 2.2.x。

解决方案是使用 2.1.x 分支 BaseWebClientTests class.