主要用于在微服务架构下作CDC(消费者驱动契约)测试。下图展现了多个微服务的调用,若是咱们更改了一个模块要如何进行测试呢?java
模拟一个股票价格查询的服务git
springcloud-contract-provider-restgithub
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-contract-verifier</artifactId> <scope>test</scope> </dependency> <build> <plugins> <plugin> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-contract-maven-plugin</artifactId> <version>2.2.1.RELEASE</version> <extensions>true</extensions> <configuration> <!--用于构建过程当中插件自动生成测试用例的基类--> <baseClassForTests> com.example.springcloudcontractproviderrest.RestBaseCase </baseClassForTests> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
既然是消费者驱动契约,我么首先须要制定契约,这里为了方便假设查询贵州茅台的股价返回值是固定的999,也能够经过正则等方式去限制返回值spring
Contract.make { description "query by id should return stock(id,price)" request { method GET() url value { // 消费者使用时请求任何 /stock/price/数字 都会被转为 /stock/price/600519 consumer regex('/stock/price/\\d+') producer "/stock/price/600519" } } response { status OK() headers { contentType applicationJson() } // 提供给消费者的默认返回 body([ id : 600519, price: 999 ]) // 服务端在测试过程当中,body须要知足的规则 bodyMatchers { jsonPath '$.id', byRegex(number()) jsonPath '$.price', byRegex(number()) } } }
主要是加载环境,而后因为不是真实环境模拟了数据库查询数据库
@SpringBootTest @RunWith(SpringRunner.class) public class RestBaseCase { @Autowired private StockController stockController; @MockBean private StockRepository stockRepository; @Before public void setup() { init(); RestAssuredMockMvc.standaloneSetup(stockController); } private void init() { Mockito.when(stockRepository.getStockById(600519)).thenReturn(new StockDTO(600519, "贵州茅台", 999L, "SH")); } }
实现咱们的服务功能,具体代码逻辑能够在项目地址中查看,而后测试看是否符合契约json
mvn clean test
架构
能够在生成(target)目录中找到 generated-test-sources 这个目录,插件为咱们自动生成而且运行的case就在其中app
public class StockTest extends RestBaseCase { @Test public void validate_shoudReturnStockIdAndPrice() throws Exception { // given: MockMvcRequestSpecification request = given(); // when: ResponseOptions response = given().spec(request) .get("/stock/price/600519"); // then: assertThat(response.statusCode()).isEqualTo(200); assertThat(response.header("Content-Type")).matches("application/json.*"); // and: DocumentContext parsedJson = JsonPath.parse(response.getBody().asString()); // and: assertThat(parsedJson.read("$.id", String.class)).matches("-?(\\d*\\.\\d+|\\d+)"); assertThat(parsedJson.read("$.price", String.class)).matches("-?(\\d*\\.\\d+|\\d+)"); } }
若是一切顺利就能够deploy了maven
模拟查询我的资产的服务,须要远程调用股票价格查询服务,计算总资产ide
springcloud-contract-consumer-rest
编写测试用例验证服务
@SpringBootTest @RunWith(SpringRunner.class) @AutoConfigureStubRunner( ids = {"com.example:springcloud-contract-provider-rest:+:stubs:8880"}, stubsMode = StubRunnerProperties.StubsMode.LOCAL ) public class StockApiTest { @Autowired private StockApi stockApi; @Test public void testStockApi() throws IOException { StockPriceDTO stockPrice = stockApi.getStockPrice(600519).execute().body(); BDDAssertions.then(stockPrice.getId()).isEqualTo(600519); BDDAssertions.then(stockPrice.getPrice()).isEqualTo(999); } }