图形QL

由于 GraphQL 本质上是 HTTP,因此您可以通过创建标准 HTTP 合同来为其编写合同,其中包含一个带有 key 和 mapping 的附加条目。metadataverifiertool=graphqlspring-doc.cn

槽的
import org.springframework.cloud.contract.spec.Contract

Contract.make {

	request {
		method(POST())
		url("/graphql")
		headers {
			contentType("application/json")
		}
		body('''
{
	"query":"query queryName($personName: String!) {\\n  personToCheck(name: $personName) {\\n    name\\n    age\\n  }\\n}\\n\\n\\n\\n",
	"variables":{"personName":"Old Enough"},
	"operationName":"queryName"
}
''')
	}

	response {
		status(200)
		headers {
			contentType("application/json")
		}
		body('''\
{
  "data": {
    "personToCheck": {
      "name": "Old Enough",
      "age": "40"
    }
  }
}
''')
	}
	metadata(verifier: [
	        tool: "graphql"
	])
}
YAML
---
request:
  method: "POST"
  url: "/graphql"
  headers:
    Content-Type: "application/json"
  body:
    query: "query queryName($personName: String!) { personToCheck(name: $personName)
      {         name    age  } }"
    variables:
      personName: "Old Enough"
    operationName: "queryName"
  matchers:
    headers:
      - key: "Content-Type"
        regex: "application/json.*"
        regexType: "as_string"
response:
  status: 200
  headers:
    Content-Type: "application/json"
  body:
    data:
      personToCheck:
        name: "Old Enough"
        age: "40"
  matchers:
    headers:
      - key: "Content-Type"
        regex: "application/json.*"
        regexType: "as_string"
name: "shouldRetrieveOldEnoughPerson"
metadata:
  verifier:
    tool: "graphql"

添加 metadata 部分将更改默认 WireMock 存根的构建方式。它现在将使用 Spring Cloud Contract 请求匹配器,例如,通过忽略空格将 GraphQL 请求的部分与真实请求进行比较。queryspring-doc.cn

生产者端设置

在创建者方面,您的配置可能如下所示。spring-doc.cn

Maven 系列
<plugin>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-contract-maven-plugin</artifactId>
    <version>${spring-cloud-contract.version}</version>
    <extensions>true</extensions>
    <configuration>
        <testMode>EXPLICIT</testMode>
        <baseClassForTests>com.example.BaseClass</baseClassForTests>
    </configuration>
</plugin>
Gradle
contracts {
	testMode = "EXPLICIT"
	baseClassForTests = "com.example.BaseClass"
}

基类将设置在随机端口上运行的应用程序。spring-doc.cn

基类
@SpringBootTest(classes = ProducerApplication.class,
		properties = "graphql.servlet.websocket.enabled=false",
		webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public abstract class BaseClass {

	@LocalServerPort int port;

	@BeforeEach
	public void setup() {
		RestAssured.baseURI = "http://localhost:" + port;
	}
}

消费者端设置

GraphQL API 的使用者端测试示例。spring-doc.cn

消费者端测试
@SpringBootTest(webEnvironment = WebEnvironment.NONE)
public class BeerControllerGraphQLTest {

	@RegisterExtension
	static StubRunnerExtension rule = new StubRunnerExtension()
			.downloadStub("com.example","beer-api-producer-graphql")
			.stubsMode(StubRunnerProperties.StubsMode.LOCAL);

	private static final String REQUEST_BODY = "{\n"
			+ "\"query\":\"query queryName($personName: String!) {\\n  personToCheck(name: $personName) {\\n    name\\n    age\\n  }\\n}\","
			+ "\"variables\":{\"personName\":\"Old Enough\"},\n"
			+ "\"operationName\":\"queryName\"\n"
			+ "}";

	@Test
	public void should_send_a_graphql_request() {
		ResponseEntity<String> responseEntity = new RestTemplate()
				.exchange(RequestEntity
						.post(URI.create("http://localhost:" + rule.findStubUrl("beer-api-producer-graphql").getPort() + "/graphql"))
						.contentType(MediaType.APPLICATION_JSON)
						.body(REQUEST_BODY), String.class);

		BDDAssertions.then(responseEntity.getStatusCodeValue()).isEqualTo(200);

	}
}