快捷搜索:  汽车  科技

微服务测试内容(契约测试带你读懂)

微服务测试内容(契约测试带你读懂)}String customerId) ;public interface AccountClient { @Ge tMapping ("/customer/ { customerId}") List<Account> findByCustomer (@PathVariable ("customerId")

契约测试

有一些有趣的工具专门用于契约测试。我们将通过两个最流行的工具一Pact 和Spring Cloud Contract来讨论这个概念。

微服务测试内容(契约测试带你读懂)(1)

使用Pact

如前文所述,契约测试的主要概念是定义使用者(Consumer) 和提供者(Provider)之间的契约,然后针对每个服务独立地进行验证。由于创建和维护契约的责任主要在于使用者端,因而这种类型的测试通常被称为使用者驱动的测试(Consumer-Driven Test)。在PactJVM中可以清楚地看到对使用者和提供者方面的划分。它提供了两个独立的库,第一个以pact-jvm-consumer为前缀,第二个以pact-jvm-provider为前缀。当然,契约是由使用者与提供者协商创建的,如图13.4 所示。

微服务测试内容(契约测试带你读懂)(2)

事实上,Pact 是一系列框架,可以为使用者驱动的契约测试提供支持。这些实现可用于不同的语言和框架。幸运的是,Pact 可以与JUnit和Spring Boot 一起使用。现在可以来考虑在我们的示例系统中实现的集成之一 即customer -service服务和account-service服务之间的集成。名为customer-service 服务的微服务将使用Feign 客户端与account-service服务进行通信。使用者端的Feign 客户定义事实上代表了我们的契约。

@FeignClient (name = "account-service")

public interface AccountClient {

@Ge tMapping ("/customer/ { customerId}")

List<Account> findByCustomer (@PathVariable ("customerId")

String customerId) ;

}

1.使用者端

要在使用者端启用具有JUnit支持的Pact 可以在项目中包含以下依赖项。

<dependency>

<groupId>au . com. dius</groupId>

<artifactId>pact-jvm-consumer-junit 2.12</artifactId>

<version>3.5.12</version>

<scope>test</scope>

</ dependency>

现在我们唯一要做的就是创建JUnit测试类。可以通过使用@SpringBootTest注解并使用Spring Runner运行它来将其实现为标准的Spring Boot测试。要成功执行创建的测试,我们首先需要禁用发现客户端,并确保Ribbon客户端将与@Rule PactProviderRuleMk2所代表的account-service服务的桩通信。测试的关键点是callAccountClient方法,该方法使用@Pact进行注解并返回RequestResponsePact. 它定义了请求的格式和响应的内容。在测试用例执行期间,Pact 会自动生成该定义的JSON表示,它在targetpacts/addressClient-customerServiceProvider.json文件中可用。最后,调用Feign客户端中实现的方法,并在使用@PactVerification注解的测试方法中验证Pact @Rule返回的响应。以下是一个customer-service服务的使用者端契约测试的实现示例。

@RunWith (SpringRunner .class)

espringBootTest (properties = {

"account-service. ribbon. listofServers: localhost:8092"

”account- service. ribbon. eureka.enabled: false"

"eureka.client.enabled: false"

} )

public class Custome rConsumerContractTest {

@Rule

public PactProviderRuleMk2 stubProvider = new

PactProviderRuleMk2 (" customerServiceProvider" "localhost" 8092,this) ;

@Autowi red

private AccountClient accountClient;

@Pact(state - "list-of-3-accounts" provider =

"cus tome rServiceProvider" consumer = "accountClient")

public RequestResponsePact callAccountClient (PactDslWithProvider

builder) {

return builder .given("list-of -3-accounts") . uponReceiving ("test-

account-service")

.path("/customer/1") 。method ("GET") . willRespondwith() .status (200)

.body("[{\"id\":\"1\" \"number\":\"123\",\"balance\":5000} {\"id\":\"2\"

\"number\":\"124\" \"balance\":5000} (\"id\":\"3\" \"number\":\"125\"

\"balan ce\":50001]", "application/json") . toPact( );

}

@Test

@PactVerification (fragment - "callAccountClient")

public void verifyAddressCollectionPact() (

List<Account> accounts = accountClient. findByCustomer ("1");

Assert.assertEquals(3 accounts.size( ) );

}

}

在targetpacts目录中生成的JSON测试结果文件必须在提供者端可用。最简单的解决方案假设它只能使用@PactFolder注解访问生成的文件。当然,它要求提供者可以访问targetpacts目录。虽然它应该可以用于我们的示例,因为它的源代码存储在同一个Git存储库中,但它并不是我们的目标解决方案。幸运的是,我们可以使用Pact Broker在网络中发布Pact测试结果。Pact Broker是一个存储库服务器,它可以提供用于发布和使用Pact文件的HTTP API.

微服务测试内容(契约测试带你读懂)(3)

开发人员可以使用Docker镜像在本地启动Pact Broker。它需要Postgres数据库作为后端存储,因而也需要启动带Postgres的容器。以下是所需的Docker命令。

docker run -d --name postgres -P 5432:5432 -e POSTGRES USER=oauth -e

POSTGRES PASSWORD-oauth123 -e POSTGRES DB- oauth postgres

docker run -d --name pact-broker - - link postgres :postgres -e

PACT BROKER DATABASE USERNAME oauth -e

PACT BROKER DATABASE PASSWORD oauth123 -e

PACT BROKER DATABASE HOST-postgres -e PACT BROKER DATABASE NAME=oauth -P

9080:80 dius/pact_ broker

在Docker.上运行Pact Broker之后,必须在那里发布我们的测试报告。可以使用Maven插件pactjvm-provider. maven.2.12 轻松执行此操作。如果运行mvn clean install pack:publish命令,则放置在/target/pacts 目录中的所有文件都将被发送到代理的HTTP API。

<plugin>

<groupId>au. com. dius</groupId>

<artifactId>pact-jvm-provider -maven 2.12</artifactId>

<version>3.5.12</version>

<configuration>

<pactBrokerUrl>http://192.168. 99.100:9080</pactBrokerUrl>

</configuration>

</plugin>

可以使用htp://92.168.99.100:9080上提供的Web控制台显示已发布的Pact的完整列表。它还提供有关上次验证日期的信息以及列表中每个Pact的详细信息,如图13.5所示即为其屏幕截图。

微服务测试内容(契约测试带你读懂)(4)

2.生产者端

假设使用者创建了一个Pact并将其发布在代理上,则开发人员可以继续在提供者端实现验证测试。要在提供者端启用具有JUnit支持的Pact 可以在项目中包含pact-jvm-provider-junit依赖项。

还有另一-个框架也可以使用,即pact-jvm-provider-spring. 该库允许开发人员使用Spring和JUnit对提供者运行契约测试。可以在Maven的pom.xml的以下片段中看到所需依赖项的列表。

<dependency>

<groupId>au. com. dius</groupId>

<artifactId>pact-jvm-provider- junit_ 2. 12</artifactId>

<version>3.5.12</version>

<scope>test</ scope>

</dependency>

<dependency>

<groupId>au. com.dius</groupId>

<artifactId>pact-jvm-provider-spring 2. 12</artifactId>

<version>3.5.12</version>

<scope>test</scope>

</ dependency>

由于Spring专用库的存在,开发人员可以使用SpringRestPactRunner而不是默认的PactRunner。反过来,这也允许开发人员使用Spring测试注解,如@MockBean。 在下面的JUnit测试中,我们模拟了AccountRepository bean。 它将返回使用者端测试所需的3个对象。测试将自动启动Spring Boot应用程序并调用/customer/ {customerld}端点。

微服务测试内容(契约测试带你读懂)(5)

另外还有两件重要的事情。通过使用@Provider和@State注解,我们需要设置与@Pact注解中使用者端的测试设置相同的名称。最后,通过在测试类上声明@PactBroker 可以为Pact的存储库提供连接设置。以下是使用Pact的测试示例,它将验证由customer-service服务发布的契约。

@RunWith (Spr ingRestPactRunner. class)

@Provider (" customerServiceProvider")

@PactBroker(host = "192.168.99.100" port. = "9080")

@SpringBootTest (webEnvi ronment =

SpringBootTest . WebEnvironment. DEFINED PORT properties = {

"eureka.cllent .enabled: false" ))

public class AccountProviderContractTest {

@MockBean

private AccountRepository repository;

@TestTarget

public final Target target - new HttpTarget (8091);

@State ("list-of-3-accounts")

public void toDefaultState( ) {

List<Account> accounts = new ArrayList<> () ;

accounts.add (new Account ("1" "123", 5000, "1") );

accounts . add (new Account("2" "124", 5000, "1") );

accounts . add (new Account("3" "125", 5000, "1") );

when (repository. findByCustomerId ("1") ) . thenReturn(accounts);

}

}

微服务测试内容(契约测试带你读懂)(6)

本文给大家讲解的内容是测试Java微服务中的契约测试

1.下篇文章给大家讲解的是如何使用Spring Cloud Contract

2.觉得文章不错的朋友可以转发此文关注小编,有需要的可以私信小编获取资料;

3.感谢大家的支持!

猜您喜欢: