1.概述

在本文中,我们将探讨假客户端集成测试

我们将创建一个基本的打开装客户端我们将编写一个简单的集成测试借助WireMock

在那之后,我们将添加一个丝带配置到我们的客户机并且为它建立一个集成测试。最后,我们会配置一个尤里卡测试容器并测试此设置以确保我们的整个配置按预期工作。

2.装客户端

要设置我们的外部客户机,我们应该首先添加春云OpenFeignMaven的依赖:

<依赖> < groupId > org.springframework。云< / groupId > < artifactId > spring-cloud-starter-openfeign < / artifactId > < / >的依赖

之后,让我们创建一个类为我们的模型:

公共类书{私有字符串标题;私有字符串作者;}

最后,让我们创建我们的Feign Client接口:

@FeignClient(value="simple-books-client", url="${Book .service.url}") public interface BooksClient {@RequestMapping("/books") List getBooks();}

现在我们有一个假客户端,它检索一个列表从REST服务。现在,让我们继续写一些集成测试。

3.WireMock

3.1.设置WireMock服务器

如果我们想测试我们的BooksClient,我们需要一个模拟服务来提供/书终点。我们的客户将调用此模拟服务。为此,我们将使用WireMock。

我们加上WireMockMaven的依赖:

<依赖> < groupId > com.github。tomakehurst wiremock test 

并配置模拟服务器:

@TestConfiguration公共类WireMockConfig{@Autowired private WireMockServer WireMockServer;@Bean(initMethod=“start”,destromethod=“stop”)公共WireMockServer mockBooksService(){返回新的WireMockServer(9561);}

我们现在有一个正在运行的模拟服务器,在端口9651上接受连接。

3.2. 设置模拟

让我们添加属性book.service.url对我们application-test.yml指向WireMockServer端口:

预订:服务:网址:http://localhost:9561

让我们准备一个模拟反应get-books-response.json/书终点:

[{"title": "Dune", "author": "Frank Herbert"}, {"title": "Foundation", "author": "Isaac Asimov"}]

现在让我们配置模拟响应得到请求的/书终点:

public class BookMocks {public static void setupMockBooksResponse(WireMockServer mockService) throws IOException {mockService. stubfor (WireMock.get(WireMock.urlEqualTo("/books")) .willReturn(WireMock.aResponse() .withStatus(HttpStatus.OK.value()) .withHeader("Content-Type"),mediattype . application_json_value) .withBody(copyToString(BookMocks.class.getClassLoader().getResourceAsStream("payload/get-books-response.json"), defaultCharset()))));} }

此时,所有必需的配置都已就绪。让我们继续编写第一个测试。

4.我们的第一次集成测试

让我们创建一个集成测试BooksClientIntegrationTest:

@SpringBootTest@ActiveProfiles(“test”)@EnableConfigurationProperties@ExtendWith(SpringExtension.class)@ContextConfiguration(classes={WireMockConfig.class})class BooksClientIntegrationTest{@Autowired private WireMockServer mockbookservice;@Autowired private BooksClient BooksClient;@beforeach void setUp()引发IOException{BookMocks.setupMockBooksResponse(mockbookservice);}/…}

在这一点,我们有SpringBootTest配置一个WireMockServer准备好返回预定义的/书端点由BooksClient

最后,让我们添加测试方法:

@Test public void whenGetBooks_thenBooksShouldBeReturned() {assertFalse(bookscclient . getbooks ().isEmpty());} @Test public void whenGetBooks_thenTheCorrectBooksShouldBeReturned() {assertTrue(bookscclient . getbooks () .containsAll(asList(new Book("Dune", "Frank Herbert"), new Book("Foundation", "Isaac Asimov"))));}

5.结合丝带

现在让我们通过添加负载平衡功能来改进客户机提供的丝带。

在客户端接口中,我们需要做的就是删除硬编码的服务URL,并通过服务名称引用服务book服务:

@FeignClient("books-service") public interface BooksClient{…

接下来,添加Netflix丝带Maven的依赖:

<依赖> < groupId > org.springframework。云< / groupId > < artifactId > spring-cloud-starter-netflix-ribbon < / artifactId > < / >的依赖

最后,在application-test.yml文件,我们现在应该删除book.service.url而是定义功能区listOfServers:

books-service: ribbon: listOfServers: http://localhost:9561

现在让我们运行BooksClientIntegrationTest一次。它应该会通过,确认新的设置如预期的那样工作。

5.1.动态端口配置

如果我们不想硬编码服务器的端口,我们可以配置WireMock在启动时使用动态端口。

为此,让我们创建另一个测试配置,RibbonTestConfig:

@TestConfiguration @ActiveProfiles(" ribbontest ") public class RibbonTestConfig {@Autowired private WireMockServer mockBooksService;@Autowired私有WireMockServer secondMockBooksService;@Bean(initMethod = "start", destroyMethod = "stop") public WireMockServer mockBooksService() {return new WireMockServer(options().dynamicPort());} @Bean(name="secondMockBooksService", initMethod =" start", destroyMethod =" stop") public WireMockServer secondBooksMockService() {return new WireMockServer(options().dynamicPort());} @Bean public ServerList ribbonServerList() {return new StaticServerList<>(new Server("localhost", mockBooksService.port()), new Server("localhost", secondMockBooksService.port()));} }

这个配置设置了两个WireMock服务器,每个服务器运行在运行时动态分配的不同端口上。此外,它还使用两个模拟服务器配置Ribbon服务器列表。

5.2。负载平衡测试

现在我们已经配置好了Ribbon负载平衡器,我们来确定一下BooksClient正确地在两个模拟服务器之间交替:

@SpringBootTest@ActiveProfiles(“功能区测试”)@EnableConfigurationProperties@ExtendWith(SpringExtension.class)@ContextConfiguration(class={RibbonTestConfig.class})类LoadBalancerBooksClientIntegrationTest{@Autowired private WireMockServer mockbookservice;@Autowired private WireMockServer secondmockbookservice;@Autowired private BooksClient BooksClient;@beforeach void setUp()抛出IOException{setupMockBooksResponse(mockbookservice);setupMockBooksResponse(secondmockbookservice);}@Test void whenGetBooks\u thenRequestsareloaddbalanced{for(int k=0;k<10;k++){booksClient.getBooks();}mockbookservice.verify(大于(0),getRequestedFor(WireMock.urlEqualTo(“/books”);second mockbookservice.verify(大于(0),getRequestedFor(WireMock.urlEqualTo(“/books”);}@Test public-void,当书籍返回正确的书籍时({assertTrue(booksClient.getBooks)().containsAll(asList(新书(“沙丘”、“弗兰克·赫伯特”)、新书(“基金会”、“艾萨克·阿西莫夫”);}

6.尤里卡积分

到目前为止,我们已经看到了如何测试使用Ribbon进行负载平衡的客户机。但是什么呢如果我们的设置使用像Eureka这样的服务发现系统。我们应该编写一个集成测试,以确保BooksClient像预期的那样工作在这样的背景下也是如此。

为了这个目的,我们将运行一个Eureka服务器作为测试容器。然后我们启动并注册一个mockbook服务用我们的尤利卡容器。最后,一旦安装完成,我们可以对它运行测试。

在继续之前,让我们添加TestcontainersNetflix尤里卡客户Maven的依赖关系:

org.springframework.cloudspringcloudstarter-netflix-eureka-clientorg.testcontainerstestcontainerstest

6.1.TestContainer设置

让我们创建一个TestContainer配置,将旋转我们的Eureka服务器:

public class EurekaContainerConfig {public static class Initializer implements ApplicationContextInitializer {public static GenericContainer eurekaServer = new GenericContainer("springcloud/eureka").withExposedPorts(8761);@Override public void initialize(@NotNull ConfigurableApplicationContext ConfigurableApplicationContext) {Startables.deepStart(Stream.of(eurekaServer)).join();TestPropertyValues .of("eureka.client. serviceurl . defaultzone =http://localhost:" + eurekaserer . getfirstmappedport ().toString() + "/eureka") .applyTo(configurableApplicationContext);}}}

正如我们所看到的,上面的初始化式启动了容器。然后它公开端口8761,Eureka服务器正在侦听该端口。

最后,在Eureka服务启动后,我们需要更新eureka.client.serviceUrl.defaultZone财产。这定义了用于服务发现的Eureka服务器的地址。

6.2。注册模拟服务器

现在我们的Eureka服务器已经启动并运行,我们需要注册一个mockbooks服务。我们只需简单地创建一个RestController:

@Configuration @RestController @ActiveProfiles("eureka-test") public class MockBookServiceConfig {@RequestMapping("/books") public List getBooks(){返回集合。singletonList(新书(《银河系漫游指南》(Hitchhiker's Guide to the Galaxy),《道格拉斯·亚当斯》(Douglas Adams));} }

我们现在要做的,为了注册这个控制器,就是确保spring.application.name财产在我们application-eureka-test.ymlbooks服务,中使用的服务名称相同BooksClient接口。

注意:现在netflix-eureka-client库在我们的依赖项列表中,Eureka将默认用于服务发现。所以,如果我们想要我们之前的测试,不用尤利卡,继续通过,我们需要手动设置eureka.client.enabled为。这样的话,即使图书馆在路上,也BooksClient不会尝试使用Eureka来定位服务,而是使用Ribbon配置。

6.3。集成测试

再一次,我们有了所有需要的配置部分,所以让我们把它们放在一起进行测试:

@ActiveProfiles(“eureka测试”)@EnableConfigurationProperties@ExtendWith(SpringExtension.class)@SpringBootTest(classes=Application.class,webEnvironment=SpringBootTest.webEnvironment.RANDOM_PORT)@ContextConfiguration(classes={MockBookServiceConfig.class},初始值设定项={EurekaContainerConfig.Initializer.class})类ServiceDiscoveryBookClientIntegrationTest{@Autowired private BooksClient BooksClient;@Lazy@Autowired private EurekaClient EurekaClient EurekaClient;@beforeach void setUp(){wait().atMost(60秒)。直到(()->EurekaClient.getApplications().size()>0);}@Test public void when ngetbooks\u然后返回正确的书籍(){List books=booksClient.getBooks();assertEquals(1,books.size());assertEquals(新书(《银河系漫游指南》,《道格拉斯·亚当斯》),books.stream().findFirst().get();}

在这个测试中发生了一些事情。让我们一个接一个地看一下。

首先,里面的上下文初始化器EurekaContainerConfig启动Eureka服务。

然后,SpringBootTest启动books服务公开中定义的控制器的应用程序MockBookServiceConfig

因为Eureka容器和web应用程序的启动可能需要几秒钟的时间,我们需要等到books服务被注册。这发生在设置的测试。

最后,测试方法验证BooksClient在结合Eureka配置时确实能够正确工作。

7.结论

在这篇文章中,我们已经探索了为Spring Cloud Feign客户端编写集成测试的不同方法。我们从一个基本的客户端开始,在WireMock的帮助下进行了测试。之后,我们继续使用Ribbon添加负载平衡。我们编写了一个集成测试,确保我们的Feign客户端与Ribbon提供的客户端负载平衡正确工作。最后,我们还添加了Eureka服务发现功能。我们再次确保我们的客户仍然按照预期工作。

和往常一样,完整的代码是可用的在GitHub

通用的底部

通过学习的春天课程:

>>看看课程
这篇文章的评论已经关闭!