如何从 junit 测试生成 spring restdocs 和 Pact.io pact?
How to generate both spring restdocs and Pact.io pact from junit test?
使用 spring boot 和 mockmvc ,我用下面的 @beforeEach
方法测试 class:
@BeforeEach
void setUp(WebApplicationContext context,
RestDocumentationContextProvider restDocumentation) {
MockMvcRestDocumentationConfigurer configurer = documentationConfiguration(restDocumentation);
configurer.operationPreprocessors()
.withRequestDefaults(prettyPrint())
.withResponseDefaults(prettyPrint());
configurer.snippets()
.withDefaults(
httpRequest(),
httpResponse()
);
this.mockMvc = MockMvcBuilders.webAppContextSetup(context)
.apply(configurer)
.build();
及以下测试方法:
@Test
void createAdminHttpRequest() throws Exception {
var adminDTO = HandlerTestObjectGenerator.createFixedAdminDTO();
mockMvc.perform(
RestDocumentationRequestBuilders
.post("/api/admins")
.content(objectMapper.writeValueAsString(adminDTO))
.contentType(MediaType.APPLICATION_JSON_UTF8)
).andExpect(status().isCreated())
.andDo(document("create-admin",
preprocessRequest(),
preprocessResponse(),
requestFields(
usernameFieldDescriptor,
passwordFieldDescriptor,
rolesFieldDescriptor
),
responseFields(
admin_adminIdFieldDescriptor,
admin_usernameFieldDescriptor,
admin_rolesFieldDescriptor
),
SpringCloudContractRestDocs.dslContract(),
));
}
此测试运行良好并生成 spring rest docs 文档和 groovy 合同。
但是对于前端(反应)测试,我需要生成 Pact.io 合约,它是独立于框架的。
问题
所以,我的问题是是否可以使用单一 @Test
方法同时生成 spring rest 文档和 pact.io 协议?
我的研究
到目前为止,我发现契约是使用其自己的 rest 生成器从 @Pact
注释方法生成的。
另外,我发现了这段对话:
https://gitter.im/spring-cloud/spring-cloud-contract/archives/2018/08/06 并且我正在尝试实现自己的 Maven 插件以将 groovy 合同转换为契约,但是 BodyConverter
class 中似乎有错误并且我收到以下异常:
java.lang.UnsupportedOperationException: use the array(String name) form
at au.com.dius.pact.consumer.dsl.PactDslJsonBody.array(PactDslJsonBody.java:673)
我的maven插件代码示例:
初始化:
private PactContractConverter pactContractConverter = new PactContractConverter();
private ContractVerifierDslConverter contractDslConverter = new ContractVerifierDslConverter();
转化率:
private void processFiles(List<File> contractFiles) throws Exception {
for(File file : contractFiles) {
logger.info("Processing " + file.getAbsolutePath());
Collection<Contract> contracts = contractDslConverter.convertFrom(file);
Collection<Pact> pacts = pactContractConverter.convertTo(contracts);
String jsonPacts = mapper.writeValueAsString(pactContractConverter.store(pacts));
File pactsFile = new File(outputDir, file.getName() + "_pact.json");
FileUtils.writeByteArrayToFile(pactsFile, jsonPacts.getBytes());
logger.info("Generated pact file: " + pactsFile.getAbsolutePath());
}
}
但是我遇到了上面提到的异常。有直接调用方法,抛出UnsupportedOperationException
。我找到了其他方法 array(String name)
,但似乎不是从转换器代码中调用的。
让我们从这个声明开始:
But for front-end (react) testing, I need to generate Pact.io contract, which is framework independent.
您可以在多语言世界中使用 Spring Cloud Contract。只需使用 Docker (https://spring.io/blog/2018/02/13/spring-cloud-contract-in-a-polyglot-world) and https://cloud.spring.io/spring-cloud-static/spring-cloud-contract/2.2.0.RELEASE/reference/html/docker-project.html
回到你的问题
So, my question is if it is possible to generate both spring rest docs and pact.io pact using single @Test method?
让我们换一种方式...既然您已经有了 DSL,我想您也想获得 Pact 文件。如果您查看此部分 (https://cloud.spring.io/spring-cloud-static/spring-cloud-contract/2.2.0.RELEASE/reference/html/howto.html#how-to-generate-pact-from-scc) 下的文档,您将看到您的问题的准确答案。添加一个插件就足够了,在你的测试生成后,DSL 会将这些 DSL 转换为其他东西,例如契约文件。
使用Maven插件的例子
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<id>convert-dsl-to-pact</id>
<phase>process-test-classes</phase>
<configuration>
<classpathScope>test</classpathScope>
<mainClass>
org.springframework.cloud.contract.verifier.util.ToFileContractsTransformer
</mainClass>
<arguments>
<argument>
org.springframework.cloud.contract.verifier.spec.pact.PactContractConverter
</argument>
<argument>${project.basedir}/target/pacts</argument>
<argument>
${project.basedir}/src/test/resources/contracts
</argument>
</arguments>
</configuration>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
</plugin>
如果您修改 ${project.basedir}/src/test/resources/contracts
以指向从 REST Docs 测试中转储 DSL 的位置,您会将 PACT 文件转储到 ${project.basedir}/target/pacts
。下面是 Gradle
的类似示例
task convertContracts(type: JavaExec) {
main = "org.springframework.cloud.contract.verifier.util.ToFileContractsTransformer"
classpath = sourceSets.test.compileClasspath
args("org.springframework.cloud.contract.verifier.spec.pact.PactContractConverter",
"${project.rootDir}/build/pacts", "${project.rootDir}/src/test/resources/contracts")
}
使用 spring boot 和 mockmvc ,我用下面的 @beforeEach
方法测试 class:
@BeforeEach
void setUp(WebApplicationContext context,
RestDocumentationContextProvider restDocumentation) {
MockMvcRestDocumentationConfigurer configurer = documentationConfiguration(restDocumentation);
configurer.operationPreprocessors()
.withRequestDefaults(prettyPrint())
.withResponseDefaults(prettyPrint());
configurer.snippets()
.withDefaults(
httpRequest(),
httpResponse()
);
this.mockMvc = MockMvcBuilders.webAppContextSetup(context)
.apply(configurer)
.build();
及以下测试方法:
@Test
void createAdminHttpRequest() throws Exception {
var adminDTO = HandlerTestObjectGenerator.createFixedAdminDTO();
mockMvc.perform(
RestDocumentationRequestBuilders
.post("/api/admins")
.content(objectMapper.writeValueAsString(adminDTO))
.contentType(MediaType.APPLICATION_JSON_UTF8)
).andExpect(status().isCreated())
.andDo(document("create-admin",
preprocessRequest(),
preprocessResponse(),
requestFields(
usernameFieldDescriptor,
passwordFieldDescriptor,
rolesFieldDescriptor
),
responseFields(
admin_adminIdFieldDescriptor,
admin_usernameFieldDescriptor,
admin_rolesFieldDescriptor
),
SpringCloudContractRestDocs.dslContract(),
));
}
此测试运行良好并生成 spring rest docs 文档和 groovy 合同。
但是对于前端(反应)测试,我需要生成 Pact.io 合约,它是独立于框架的。
问题
所以,我的问题是是否可以使用单一 @Test
方法同时生成 spring rest 文档和 pact.io 协议?
我的研究
到目前为止,我发现契约是使用其自己的 rest 生成器从 @Pact
注释方法生成的。
另外,我发现了这段对话:
https://gitter.im/spring-cloud/spring-cloud-contract/archives/2018/08/06 并且我正在尝试实现自己的 Maven 插件以将 groovy 合同转换为契约,但是 BodyConverter
class 中似乎有错误并且我收到以下异常:
java.lang.UnsupportedOperationException: use the array(String name) form
at au.com.dius.pact.consumer.dsl.PactDslJsonBody.array(PactDslJsonBody.java:673)
我的maven插件代码示例:
初始化:
private PactContractConverter pactContractConverter = new PactContractConverter();
private ContractVerifierDslConverter contractDslConverter = new ContractVerifierDslConverter();
转化率:
private void processFiles(List<File> contractFiles) throws Exception {
for(File file : contractFiles) {
logger.info("Processing " + file.getAbsolutePath());
Collection<Contract> contracts = contractDslConverter.convertFrom(file);
Collection<Pact> pacts = pactContractConverter.convertTo(contracts);
String jsonPacts = mapper.writeValueAsString(pactContractConverter.store(pacts));
File pactsFile = new File(outputDir, file.getName() + "_pact.json");
FileUtils.writeByteArrayToFile(pactsFile, jsonPacts.getBytes());
logger.info("Generated pact file: " + pactsFile.getAbsolutePath());
}
}
但是我遇到了上面提到的异常。有直接调用方法,抛出UnsupportedOperationException
。我找到了其他方法 array(String name)
,但似乎不是从转换器代码中调用的。
让我们从这个声明开始:
But for front-end (react) testing, I need to generate Pact.io contract, which is framework independent.
您可以在多语言世界中使用 Spring Cloud Contract。只需使用 Docker (https://spring.io/blog/2018/02/13/spring-cloud-contract-in-a-polyglot-world) and https://cloud.spring.io/spring-cloud-static/spring-cloud-contract/2.2.0.RELEASE/reference/html/docker-project.html
回到你的问题
So, my question is if it is possible to generate both spring rest docs and pact.io pact using single @Test method?
让我们换一种方式...既然您已经有了 DSL,我想您也想获得 Pact 文件。如果您查看此部分 (https://cloud.spring.io/spring-cloud-static/spring-cloud-contract/2.2.0.RELEASE/reference/html/howto.html#how-to-generate-pact-from-scc) 下的文档,您将看到您的问题的准确答案。添加一个插件就足够了,在你的测试生成后,DSL 会将这些 DSL 转换为其他东西,例如契约文件。
使用Maven插件的例子
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<id>convert-dsl-to-pact</id>
<phase>process-test-classes</phase>
<configuration>
<classpathScope>test</classpathScope>
<mainClass>
org.springframework.cloud.contract.verifier.util.ToFileContractsTransformer
</mainClass>
<arguments>
<argument>
org.springframework.cloud.contract.verifier.spec.pact.PactContractConverter
</argument>
<argument>${project.basedir}/target/pacts</argument>
<argument>
${project.basedir}/src/test/resources/contracts
</argument>
</arguments>
</configuration>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
</plugin>
如果您修改 ${project.basedir}/src/test/resources/contracts
以指向从 REST Docs 测试中转储 DSL 的位置,您会将 PACT 文件转储到 ${project.basedir}/target/pacts
。下面是 Gradle
task convertContracts(type: JavaExec) {
main = "org.springframework.cloud.contract.verifier.util.ToFileContractsTransformer"
classpath = sourceSets.test.compileClasspath
args("org.springframework.cloud.contract.verifier.spec.pact.PactContractConverter",
"${project.rootDir}/build/pacts", "${project.rootDir}/src/test/resources/contracts")
}