스프링 클라우드 컨트랙트 공식 레퍼런스를 한글로 번역한 문서입니다.
전체 목차는 여기에 있습니다.
GraphQL은 사실상 HTTP이므로, 표준 HTTP 명세contract를 만들고, metadata
항목 아래에 verifier
키를 사용해 tool=graphql
을 매핑해주면 된다.
Groovy
YAML
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"
])
}
---
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"
위와 같이 메타데이터를 추가하면 디폴트 WireMock 스텁stub을 빌드하는 방식이 변경된다. 이제 Spring Cloud Contract 요청 matcher를 사용한다. 예를 들어 GraphQL 요청의 query
부분은 공백을 무시하고 실제 요청과 비교해본다.
Producer Side Setup
프로듀서producer 측은 다음과 같이 설정할 수 있다.
Maven
Gradle
<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>
contracts {
testMode = "EXPLICIT"
baseClassForTests = "com.example.BaseClass"
}
이 베이스 클래스는 애플리케이션이 랜덤 포트에서 실행되도록 세팅한다.
Base Class
@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;
}
}
Consumer Side Setup
GraphQL API를 테스트하는 컨슈머consumer 측 예시는 다음과 같다.
Consumer Side Test
@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);
}
}
Next :
3.4.8. GRPC
GRPC 통합하기
전체 목차는 여기에 있습니다.