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;
}
}
我理解这个过滤器工厂测试代码是如何工作的
- 自定义过滤器:自定义过滤器在
TestConfig
class testRouteLocator
方法中设置
- 目标控制器:目标控制器定义为
HttpBinCompatibleController
class
testClient
发送请求,自定义应该做一些过滤,然后目标控制器应该从 testClient
.
接收请求
我对这个 shouldFailByFilterTests
TC 的期望是,在 testClient
的请求发送到目标控制器之前,该请求应该被 MyCustomFilter
拒绝。 但是请求发送到目标控制器。
我认为来自 testClient
的请求未被 testRouteLocator
代理,但我不确定
问题
- 这个问题的原因是什么?
- 还有其他方法可以测试我自己的自定义过滤器吗?
此问题与 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.
我已经实现了自定义 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;
}
}
我理解这个过滤器工厂测试代码是如何工作的
- 自定义过滤器:自定义过滤器在
TestConfig
classtestRouteLocator
方法中设置 - 目标控制器:目标控制器定义为
HttpBinCompatibleController
class
testClient
发送请求,自定义应该做一些过滤,然后目标控制器应该从 testClient
.
我对这个 shouldFailByFilterTests
TC 的期望是,在 testClient
的请求发送到目标控制器之前,该请求应该被 MyCustomFilter
拒绝。 但是请求发送到目标控制器。
我认为来自 testClient
的请求未被 testRouteLocator
代理,但我不确定
问题
- 这个问题的原因是什么?
- 还有其他方法可以测试我自己的自定义过滤器吗?
此问题与 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.