Попытки
Попытка №1
Код: Выделить всё
package com.example.gatewaydemo.filter;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.OrderedGatewayFilter;
import org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory;
import org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Flux;
import java.util.List;
import java.util.UUID;
@WebFluxTest(controllers = GatewayTest.Config.class)
@ContextConfiguration(classes = GatewayTest.Config.class)
public class GatewayTest {
@Autowired
WebTestClient client;
@Test
void test() {
client.get()
.uri("/original-path")
.exchange()
.expectStatus().isEqualTo(HttpStatus.OK);
}
@Configuration
@EnableAutoConfiguration
static class Config {
@Bean
public RouterFunction routerFunction() {
return RouterFunctions.route()
.GET("/eventual-path", request -> ServerResponse.status(HttpStatus.OK).build())
.build();
}
@Bean
public RouteLocator routeLocator() {
// suppose I want to test this RouteLocator
GatewayFilter rewriteFilter = new RewritePathGatewayFilterFactory()
.apply(config -> config.setRegexp("/original-path")
.setReplacement("/eventual-path"));
Route route = Route.async()
.id(UUID.randomUUID().toString())
.filter(new OrderedGatewayFilter(rewriteFilter, 0)) // it's important to wrap
.predicate(new PathRoutePredicateFactory()
.apply(config -> config.setPatterns(List.of("/original-path"))))
.uri("http://localhost:8080")
.build();
return () -> Flux.just(route);
}
}
}
Код: Выделить всё
4.0.0
org.springframework.boot
spring-boot-starter-parent
3.1.5
com.example
gatewaydemo
0.0.1-SNAPSHOT
gatewaydemo
gatewaydemo
17
2022.0.4
org.springframework.cloud
spring-cloud-starter
org.springframework.cloud
spring-cloud-starter-gateway
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import
org.springframework.boot
spring-boot-maven-plugin
org.projectlombok
lombok
Код: Выделить всё
2024-03-19T18:11:02.607+03:00 ERROR 14904 --- [ main] o.s.t.w.reactive.server.ExchangeResult : Request details for assertion failure:
> GET /original-path
> WebTestClient-Request-Id: [1]
No content
< 404 NOT_FOUND Not Found
< Content-Type: [application/json]
< Content-Length: [140]
{"timestamp":"2024-03-19T15:11:02.447+00:00","path":"/original-path","status":404,"error":"Not Found","message":null,"requestId":"37ea34a7"}
Попытка №2
Код: Выделить всё
@SpringBootTest
@AutoConfigureWebTestClient
public class GatewayTest {
// the rest is the same
Код: Выделить всё
2024-03-19T18:36:20.582+03:00 ERROR 8860 --- [ctor-http-nio-2] a.w.r.e.AbstractErrorWebExceptionHandler : [c0fdf3a] 500 Server Error for HTTP GET "/original-path"
io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: no further information: localhost/127.0.0.1:8080
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
*__checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
*__checkpoint ⇢ HTTP GET "/original-path" [ExceptionHandlingWebHandler]
Original Stack Trace:
Caused by: java.net.ConnectException: Connection refused: no further information
at java.base/sun.nio.ch.Net.pollConnect(Native Method) ~[na:na]
at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:672) ~[na:na]
at java.base/sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:946) ~[na:na]
at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:337) ~[netty-transport-4.1.100.Final.jar:4.1.100.Final]
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:334) ~[netty-transport-4.1.100.Final.jar:4.1.100.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:776) ~[netty-transport-4.1.100.Final.jar:4.1.100.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724) ~[netty-transport-4.1.100.Final.jar:4.1.100.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650) ~[netty-transport-4.1.100.Final.jar:4.1.100.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562) ~[netty-transport-4.1.100.Final.jar:4.1.100.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) ~[netty-common-4.1.100.Final.jar:4.1.100.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.100.Final.jar:4.1.100.Final]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.100.Final.jar:4.1.100.Final]
at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
2024-03-19T18:36:20.699+03:00 ERROR 8860 --- [ main] o.s.t.w.reactive.server.ExchangeResult : Request details for assertion failure:
> GET /original-path
> WebTestClient-Request-Id: [1]
No content
< 500 INTERNAL_SERVER_ERROR Internal Server Error
< Content-Type: [application/json]
< Content-Length: [136]
{"timestamp":"2024-03-19T15:36:20.576+00:00","path":"/original-path","status":500,"error":"Internal Server Error","requestId":"c0fdf3a"}
Код: Выделить всё
webEnvironmentКод: Выделить всё
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureWebTestClient
public class GatewayTest {
@Autowired
WebTestClient client;
@LocalServerPort
int port;
@Test
void test() {
client.get()
.uri("/original-path")
.exchange()
.expectStatus().isEqualTo(HttpStatus.OK);
}
@Configuration
@EnableAutoConfiguration
class Config {
// the same RouterFunction
@Bean
public RouteLocator routeLocator() {
GatewayFilter rewriteFilter = new RewritePathGatewayFilterFactory()
.apply(config -> config.setRegexp("/original-path")
.setReplacement("/eventual-path"));
Route route = Route.async()
.id(UUID.randomUUID().toString())
.filter(new OrderedGatewayFilter(rewriteFilter, 0))
.predicate(new PathRoutePredicateFactory()
.apply(config -> config.setPatterns(List.of("/original-path"))))
.uri("http://localhost:" + port)
.build();
return () -> Flux.just(route);
}
}
}
Код: Выделить всё
2024-03-19T19:12:15.447+03:00 ERROR 3760 --- [ main] o.s.t.w.reactive.server.ExchangeResult : Request details for assertion failure:
> GET /original-path
> WebTestClient-Request-Id: [1]
No content
< 404 NOT_FOUND Not Found
< Content-Type: [application/json]
< Content-Length: [140]
{"timestamp":"2024-03-19T16:12:15.328+00:00","path":"/original-path","status":404,"error":"Not Found","message":null,"requestId":"5930e136"}
ТАК
Я изучил несколько ответов по этой теме
- "Юнит-тест Spring Cloud Gateway RouteLocator customRouteLocator (RouteLocatorBuilderrouteLocatorBuilder)". Мне не нравится решение. Он либо предлагает протестировать RouteLocator, автоматически созданный на основе встроенных свойств
Код: Выделить всё
@RunWith(SpringRunner.class)
@SpringBootTest(properties = {
"spring.cloud.gateway.routes[0].id=test",
"spring.cloud.gateway.routes[0].uri=http://localhost:8081",
"spring.cloud.gateway.routes[0].predicates[0]=Path=/test/**",
}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class NettyRoutingFilterTests {
Код: Выделить всё
@ExtendWith( { SpringExtension.class } )
@SpringBootTest(classes = { MockConfigurer.class },
webEnvironment = WebEnvironment.RANDOM_PORT )
public class RoutingIT
Код: Выделить всё
@Configuration
public class MockConfigurer
{
private List services;
public MockConfigurer( List services)
{
this.services= services;
}
@Bean
public DiscoveryClient discoveryClient( )
{
- "Интеграционный тест Spring не работает с Spring Boot 3 и Spring Cloud Gateway". Непонятно, как работает решение, в частности, откуда извлекается WebTestClient
Код: Выделить всё
@SpringBootTest(classes = MainApplication.class, webEnvironment = DEFINED_PORT)
public class HealthControllerTest {
@Autowired
private WebTestClient webTestClient;
@Test
public void health_shouldReturnHttp200() { this.webTestClient.get().uri(PATH).accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk();
}
}
Я посетил страницу документации проекта, но не нашел конкретной главы о тестировании
Подробнее здесь: https://stackoverflow.com/questions/781 ... utelocator