gpt4 book ai didi

java - 如何对spring的网关进行单元测试?

转载 作者:行者123 更新时间:2023-11-30 05:19:12 24 4
gpt4 key购买 nike

我的网关会将流量重定向到许多不同的服务(在不同的域名下)。如何测试网关的配置?只需一项服务,我就可以设置模拟服务器(如 httpbin)并测试响应。对于多个服务,我宁愿避免启动整个 docker 网络或更改 locak dns 别名。 spring 是否提供任何轻量级的方法来测试网关?

最佳答案

以下是如何使用 API Simulator 实现您想要的目标:

package my.package;

import static com.apisimulator.embedded.SuchThat.isEqualTo;
import static com.apisimulator.embedded.SuchThat.startsWith;
import static com.apisimulator.embedded.http.HttpApiSimulation.httpApiSimulation;
import static com.apisimulator.embedded.http.HttpApiSimulation.httpRequest;
import static com.apisimulator.embedded.http.HttpApiSimulation.httpResponse;
import static com.apisimulator.embedded.http.HttpApiSimulation.simlet;
import static com.apisimulator.http.Http1Header.CONTENT_TYPE;
import static com.apisimulator.http.HttpMethod.CONNECT;
import static com.apisimulator.http.HttpMethod.GET;
import static com.apisimulator.http.HttpStatus.OK;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;

import java.time.Duration;
import java.util.Map;

import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.util.SocketUtils;

import com.apisimulator.embedded.http.JUnitHttpApiSimulation;

@RunWith(SpringRunner.class)
@SpringBootTest(
webEnvironment = RANDOM_PORT,
properties = {
"management.server.port=${test.port}", "logging.level.root=info",
// Configure the Gateway to use HTTP proxy - the API Simulator
// instance running at localhost:6090
"spring.cloud.gateway.httpclient.proxy.host=localhost",
"spring.cloud.gateway.httpclient.proxy.port=6090"
//"logging.level.reactor.netty.http.server=debug",
//"spring.cloud.gateway.httpserver.wiretap=true"
}
)
@Import(ServiceGatewayApplication.class)
public class ServiceGatewayApplicationTest
{

// Configure an API simulation. This starts up an instance
// of API Simulator on localhost, default port 6090
@ClassRule
public static final JUnitHttpApiSimulation clApiSimulation = JUnitHttpApiSimulation
.as(httpApiSimulation("svc-gateway-backends"));

protected static int managementPort;

@LocalServerPort
protected int port = 0;

protected String baseUri;
protected WebTestClient webClient;

@BeforeClass
public static void beforeClass()
{
managementPort = SocketUtils.findAvailableTcpPort();
System.setProperty("test.port", String.valueOf(managementPort));

// Configure simlets for the API simulation
// @formatter:off
clApiSimulation.add(simlet("http-proxy")
.when(httpRequest(CONNECT))
.then(httpResponse(OK))
);

clApiSimulation.add(simlet("test-domain-1")
.when(httpRequest()
.whereMethod(GET)
.whereUriPath(isEqualTo("/static"))
// The `host` header is used to determine the actual destination
.whereHeader("host", startsWith("domain-1.com"))
)
.then(httpResponse()
.withStatus(OK)
.withHeader(CONTENT_TYPE, "application/text")
.withBody("{ \"domain\": \"1\" }")
)
);

clApiSimulation.add(simlet("test-domain-2")
.when(httpRequest()
.whereMethod(GET)
.whereUriPath(isEqualTo("/v1/api/foo"))
.whereHeader("host", startsWith("domain-2.com"))
)
.then(httpResponse()
.withStatus(OK)
.withHeader(CONTENT_TYPE, "application/json; charset=UTF-8")
.withBody(
"{\n" +
" \"domain\": \"2\"\n" +
"}"
)
)
);
// @formatter:on
}

@AfterClass
public static void afterClass()
{
System.clearProperty("test.port");
}

@Before
public void setup()
{
// @formatter:off
baseUri = "http://localhost:" + port;
webClient = WebTestClient.bindToServer()
.baseUrl(baseUri)
.responseTimeout(Duration.ofSeconds(2))
.build();
// @formatter:on
}

@Test
public void test_domain1()
{
// @formatter:off
webClient.get()
.uri("/static")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).consumeWith(result ->
assertThat(result.getResponseBody()).isEqualTo("{ \"domain\": \"1\" }")
);
// @formatter:on
}

@Test
public void test_domain2()
{
// @formatter:off
webClient.get()
.uri("/v1/api/foo")
.exchange()
.expectStatus().isOk()
.expectHeader()
.contentType("application/json; charset=UTF-8")
.expectBody(Map.class).consumeWith(result ->
assertThat(result.getResponseBody()).containsEntry("domain", "2")
);
// @formatter:on
}

}

大部分代码都是基于这个GatewaySampleApplicationTests来自 Spring Cloud Gateway 项目的类。

上面假设网关具有与这些类似的路由(仅限片段):

    ...
uri: "http://domain-1.com"
predicates:
- Path=/static
...
uri: "http://domain-2.com"
predicates:
- Path=/v1/api/foo
...

关于java - 如何对spring的网关进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59825774/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com