微服务测试内容(契约测试带你读懂)
微服务测试内容(契约测试带你读懂)}String customerId) ;public interface AccountClient { @Ge tMapping ("/customer/ { customerId}") List<Account> findByCustomer (@PathVariable ("customerId")
契约测试有一些有趣的工具专门用于契约测试。我们将通过两个最流行的工具一Pact 和Spring Cloud Contract来讨论这个概念。
使用Pact如前文所述,契约测试的主要概念是定义使用者(Consumer) 和提供者(Provider)之间的契约,然后针对每个服务独立地进行验证。由于创建和维护契约的责任主要在于使用者端,因而这种类型的测试通常被称为使用者驱动的测试(Consumer-Driven Test)。在PactJVM中可以清楚地看到对使用者和提供者方面的划分。它提供了两个独立的库,第一个以pact-jvm-consumer为前缀,第二个以pact-jvm-provider为前缀。当然,契约是由使用者与提供者协商创建的,如图13.4 所示。
事实上,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.
开发人员可以使用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所示即为其屏幕截图。
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}端点。
另外还有两件重要的事情。通过使用@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);
}
}
本文给大家讲解的内容是测试Java微服务中的契约测试1.下篇文章给大家讲解的是如何使用Spring Cloud Contract
2.觉得文章不错的朋友可以转发此文关注小编,有需要的可以私信小编获取资料;
3.感谢大家的支持!