94. Customization
Tip
本部分仅对 Groovy DSL 有效
您可以通过扩展 DSL 来定制 Spring Cloud Contract Verifier,如本节其余部分所示。
94.1 扩展 DSL
您可以为 DSL 提供自己的功能。此功能的关键要求是保持静态兼容性。在本文档的后面,您可以看到以下示例:
-
创建具有可重用类的 JAR。
-
在 DSL 中引用这些类。
您可以找到完整的示例here。
94.1.1 通用 JAR
以下示例显示了可以在 DSL 中重用的三个类。
PatternUtils 包含 consumer 和 producer 所使用的函数。
package com.example;
import java.util.regex.Pattern;
/**
* If you want to use {@link Pattern} directly in your tests
* then you can create a class resembling this one. It can
* contain all the {@link Pattern} you want to use in the DSL.
*
* <pre>
* {@code
* request {
* body(
* [ age: $(c(PatternUtils.oldEnough()))]
* )
* }
* </pre>
*
* Notice that we're using both {@code $()} for dynamic values
* and {@code c()} for the consumer side.
*
* @author Marcin Grzejszczak
*/
//tag::impl[]
public class PatternUtils {
public static String tooYoung() {
//remove::start[]
return "[0-1][0-9]";
//remove::end[return]
}
public static Pattern oldEnough() {
//remove::start[]
return Pattern.compile("[2-9][0-9]");
//remove::end[return]
}
/**
* Makes little sense but it's just an example ;)
*/
public static Pattern ok() {
//remove::start[]
return Pattern.compile("OK");
//remove::end[return]
}
}
//end::impl[]
ConsumerUtils 包含 consumer 使用的功能。
package com.example;
import org.springframework.cloud.contract.spec.internal.ClientDslProperty;
/**
* DSL Properties passed to the DSL from the consumer's perspective.
* That means that on the input side {@code Request} for HTTP
* or {@code Input} for messaging you can have a regular expression.
* On the {@code Response} for HTTP or {@code Output} for messaging
* you have to have a concrete value.
*
* @author Marcin Grzejszczak
*/
//tag::impl[]
public class ConsumerUtils {
/**
* Consumer side property. By using the {@link ClientDslProperty}
* you can omit most of boilerplate code from the perspective
* of dynamic values. Example
*
* <pre>
* {@code
* request {
* body(
* [ age: $(ConsumerUtils.oldEnough())]
* )
* }
* </pre>
*
* That way it's in the implementation that we decide what value we will pass to the consumer
* and which one to the producer.
*
* @author Marcin Grzejszczak
*/
public static ClientDslProperty oldEnough() {
//remove::start[]
// this example is not the best one and
// theoretically you could just pass the regex instead of `ServerDslProperty` but
// it's just to show some new tricks :)
return new ClientDslProperty(PatternUtils.oldEnough(), 40);
//remove::end[return]
}
}
//end::impl[]
ProducerUtils 包含 producer 使用的功能。
package com.example;
import org.springframework.cloud.contract.spec.internal.ServerDslProperty;
/**
* DSL Properties passed to the DSL from the producer's perspective.
* That means that on the input side {@code Request} for HTTP
* or {@code Input} for messaging you have to have a concrete value.
* On the {@code Response} for HTTP or {@code Output} for messaging
* you can have a regular expression.
*
* @author Marcin Grzejszczak
*/
//tag::impl[]
public class ProducerUtils {
/**
* Producer side property. By using the {@link ProducerUtils}
* you can omit most of boilerplate code from the perspective
* of dynamic values. Example
*
* <pre>
* {@code
* response {
* body(
* [ status: $(ProducerUtils.ok())]
* )
* }
* </pre>
*
* That way it's in the implementation that we decide what value we will pass to the consumer
* and which one to the producer.
*/
public static ServerDslProperty ok() {
// this example is not the best one and
// theoretically you could just pass the regex instead of `ServerDslProperty` but
// it's just to show some new tricks :)
return new ServerDslProperty( PatternUtils.ok(), "OK");
}
}
//end::impl[]
94.1.2 向项目添加依赖项
为了使插件和 IDE 能够引用常见的 JAR 类,您需要将依赖项传递给您的项目。
94.1.3 在项目的依存关系中测试依存关系
首先,添加公共 jar 依赖项作为测试依赖项。因为您的 Contract 文件在测试资源路径上可用,所以常见的 jar 类自动在 Groovy 文件中变为可见。以下示例显示如何测试依赖关系:
Maven.
<dependency>
<groupId>com.example</groupId>
<artifactId>beer-common</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
Gradle.
testCompile("com.example:beer-common:0.0.1.BUILD-SNAPSHOT")
94.1.4 在插件的依赖关系中测试依赖关系
现在,必须添加插件的依赖关系,以便在运行时重用,如以下示例所示:
Maven.
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<version>${spring-cloud-contract.version}</version>
<extensions>true</extensions>
<configuration>
<packageWithBaseClasses>com.example</packageWithBaseClasses>
<baseClassMappings>
<baseClassMapping>
<contractPackageRegex>.*intoxication.*</contractPackageRegex>
<baseClassFQN>com.example.intoxication.BeerIntoxicationBase</baseClassFQN>
</baseClassMapping>
</baseClassMappings>
</configuration>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>beer-common</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
</plugin>
Gradle.
classpath "com.example:beer-common:0.0.1.BUILD-SNAPSHOT"
94.1.5 在 DSL 中引用类
现在,您可以在 DSL 中引用您的类,如以下示例所示:
package contracts.beer.rest
import com.example.ConsumerUtils
import com.example.ProducerUtils
import org.springframework.cloud.contract.spec.Contract
Contract.make {
description("""
Represents a successful scenario of getting a beer
given:
Client 够老了
when:
他申请啤酒
then:
我们给他啤酒
""")
request {
method 'POST'
url '/check'
body(
age: $(ConsumerUtils.oldEnough())
)
headers {
contentType(applicationJson())
}
}
response {
status 200
body("""
{
"status": "${value(ProducerUtils.ok())}"
}
""")
headers {
contentType(applicationJson())
}
}
}
Tip
您可以通过将convertToYaml
设置为true
来设置 Spring Cloud Contract 插件。这样,您将不必将具有扩展功能的依赖项添加到使用方,因为使用方将使用 YAMLContract 而不是 GroovyContract。