How Can I Provide Dynamic Values to a Contract?

与存根相关的最大挑战之一是它们的重用性。只有它们得到广泛使用时,它们才能达到目标。请求和响应元素的硬编码值(例如日期和 ID)通常使得该过程变得困难。考虑以下 JSON 请求:

One of the biggest challenges related to stubs is their reusability. Only if they can be widely used can they serve their purpose. The hard-coded values (such as dates and IDs) of request and response elements generally make that difficult. Consider the following JSON request:

{
    "time" : "2016-10-10 20:10:15",
    "id" : "9febab1c-6f36-4a0b-88d6-3b6a6d81cd4a",
    "body" : "foo"
}

现在考虑以下 JSON 响应:

Now consider the following JSON response:

{
    "time" : "2016-10-10 21:10:15",
    "id" : "c4231e1f-3ca9-48d3-b7e7-567d55f0d051",
    "body" : "bar"
}

想象一下设置 time 字段的正确值(假设此内容由数据库生成)所需的麻烦,包括更改系统中的时钟或提供数据提供程序的存根实现。id 字段与此相同。你可以创建 UUID 生成器的存根实现,但这样做毫无意义。

Imagine the pain required to set the proper value of the time field (assume that this content is generated by the database) by changing the clock in the system or by providing stub implementations of data providers. The same is related to the id field. You could create a stubbed implementation of UUID generator, but doing so makes little sense.

因此,作为消费者,你希望发送与任何形式的时间或任何 UUID 匹配的请求。通过这种方式,你的系统照常工作,生成数据而无需你存根任何事物。假设在上述 JSON 中,最重要的部分是 body 字段。你可以关注它并为其他字段提供匹配。换句话说,你希望存根按如下方式工作:

So, as a consumer, you want to send a request that matches any form of a time or any UUID. That way, your system works as usual, generating data without you having to stub out anything. Assume that, in case of the aforementioned JSON, the most important part is the body field. You can focus on that and provide matching for other fields. In other words, you would like the stub to work as follows:

{
    "time" : "SOMETHING THAT MATCHES TIME",
    "id" : "SOMETHING THAT MATCHES UUID",
    "body" : "foo"
}

在响应方面,作为消费者,你需要一个你可以操作的具体值。因此,以下 JSON 有效:

As far as the response goes, as a consumer, you need a concrete value on which you can operate. Consequently, the following JSON is valid:

{
    "time" : "2016-10-10 21:10:15",
    "id" : "c4231e1f-3ca9-48d3-b7e7-567d55f0d051",
    "body" : "bar"
}

在前面的部分中,我们从合同生成了测试。因此,从生产者的角度来看,情况看起来大不相同。我们解析提供的合同,并在测试中,我们希望向你的端点发送一个真实的请求。因此,对于请求的生产者来说,我们不能有任何匹配。我们需要生产者后端可以处理的具体值。因此,以下 JSON 将有效:

In the previous sections, we generated tests from contracts. So, from the producer’s side, the situation looks much different. We parse the provided contract, and, in the test, we want to send a real request to your endpoints. So, for the case of a producer for the request, we cannot have any sort of matching. We need concrete values on which the producer’s backend can work. Consequently, the following JSON would be valid:

{
    "time" : "2016-10-10 20:10:15",
    "id" : "9febab1c-6f36-4a0b-88d6-3b6a6d81cd4a",
    "body" : "foo"
}

另一方面,从合同有效性的角度来看,响应不一定必须包含 timeid 的具体值。假设你已在生产者端生成这些值。同样,你必须执行大量存根以确保始终返回相同的值。这就是为什么从生产者的角度来看,你可能想要以下响应:

On the other hand, from the point of view of the validity of the contract, the response does not necessarily have to contain concrete values for time or id. Suppose you generate those on the producer side. Again, you have to do a lot of stubbing to ensure that you always return the same values. That is why, from the producer’s side, you might want the following response:

{
    "time" : "SOMETHING THAT MATCHES TIME",
    "id" : "SOMETHING THAT MATCHES UUID",
    "body" : "bar"
}

那么你可以如何为消费者提供匹配器,并为生产者提供具体值(以及在其他时间相反)?Spring Cloud Contract 让你可以提供一个动态值。这意味着它可以因通信的双方而异。

How can you then provide a matcher for the consumer and a concrete value for the producer (and the opposite at some other time)? Spring Cloud Contract lets you provide a dynamic value. That means that it can differ for both sides of the communication.

Дополнительные сведения об этом вы можете прочитать в разделе Contract DSL.

You can read more about this in the Contract DSL section.

阅读 Groovy docs related to JSON 以了解如何正确构建请求和响应体。

Read the Groovy docs related to JSON to understand how to properly structure the request and response bodies.