PACT - 使用提供者状态
PACT - Using provider state
我正在尝试使用 pact 来验证 spring 启动微服务。我已经从消费者生成了协议文件,并使用协议代理在提供者端对其进行了验证。
我有另一个用例,在根据实际服务响应验证协议文件之前,我需要执行一些代码。我阅读了有关状态更改 URL 和关闭状态更改以实现它的信息,但无法获得如何实现此目的的示例。有人可以帮忙吗?
我的具体情况是:我创建了一个合同来更新ID为1234的客户(名字:测试姓氏:用户)。
如果这个客户不存在,那么我需要通过从契约文件中的更新请求中读取名字、姓氏、id 和附加信息(城市、州、phone 号)通过状态更改代码。
所以我的问题是,我可以通过状态更改从 pact 文件中读取请求数据,而不是在验证端配置名字、姓氏和 ID 吗?
状态更改 URL 是您在提供程序上创建的一个挂钩,它允许 Pact 告诉提供程序它在测试开始时应该处于什么状态。在每次测试运行之前,模拟消费者在您的提供者上点击状态更改 URL,并告诉它测试期望的状态名称。
你需要做两件事:
- 配置状态更改URL
- 在提供程序上实施状态更改端点
配置状态更改URL
您可以在提供商验证设置中配置状态更改 URL。例如,使用 the maven plugin:
<serviceProvider>
<name>provider1</name>
<stateChangeUrl>http://localhost:8080/tasks/pactStateChange</stateChangeUrl>
...
hasPactWith('consumer1') {
stateChangeUrl = url('http://localhost:8080/tasks/pactStateChange')
...
这两个都告诉模拟消费者使用 localhost:8080/tasks/pactStateChange
在每次测试之前更改提供者的状态。
实现状态改变端点
上面链接的文档告诉我们,默认情况下,请求的格式是 POST 您的状态字符串和任何参数的请求:
{ "state" : "a provider state description", "params": { "a": "1", "b": "2" } }
要使用它,您需要在提供程序上实现类似以下未经测试的代码:
@RequestMapping(value = "tasks/pactStateChange", method = RequestMethod.POST)
ResponseEntity<?> stateChange(@RequestBody ProviderState state) {
if (state.state == "no database") {
// Set up state for the "no database" case here
} else if state.state == "Some other state" {
// Set up state here
} else if ... // Other states go here
...
}
return ResponseEntity.ok().build()
}
请原谅该示例中的任何 spring 引导错误 - 我不是 spring 引导人员,但您可以看到一般原则。
随着状态的改变 URL,pact 不会告诉提供商任何设置细节。它只是告诉提供者您在测试中使用的预先商定的状态字符串。这可能类似于 "foo exists"
。然后,在实现状态更改 URL 的处理程序时,您会检测到 "foo exists"
,并在那里进行任何显式设置。
if (state.state == "foo exists") {
// do whatever you need to set up so that foo exists
repository.clear()
repository.insert(new Foo("arguments that foo needs",12))
}
如果您想了解有关提供者状态的更多信息,请阅读 wiki page on provider states。
如何根据您的具体情况执行此操作
您问的是:
Can i read the request data from pact file through state change instead of configuring the first name,last name and id in the verification side?
您可能对合同测试的意图感到困惑 - 每个测试都是状态和请求的组合。
所以不用一个测试来表示:
- 我的测试是请求客户更新。如果客户存在,那么我期望 X 响应,如果不存在,那么我期望 Y 响应
你用两个测试说:
当我向客户记录提交更新时(在客户存在的状态下),那么我期望X响应。
当我提交更新客户记录时(在客户不存在的状态下),那么我期望Y响应。
这些测试是您的 Pact 合同中的两个独立项目。
目的是不在合同中包含设置的详细信息。在消费者方面,您的状态只是一个字符串,类似于 "Customer with id=1234 exists".
在提供商端,您的状态更改端点会检测到 URL 并根据需要创建状态。这通常以硬编码的方式完成:
if (state == "Customer with id=1234 exists") {
Database.Clear()
Database.Insert(new Customer(1234, "John","Smith"))
} else if (state == "No customers exist") {
Database.Clear()
}
您不想通过解析状态字符串以参数化的方式执行此操作,因为那样您将在测试消费者和提供者之间创建一个新的复杂合同。
消费者测试不应该知道如何设置提供者状态,他们应该只知道测试需要什么状态(仅按名称)。同样,提供者不需要知道正在测试什么,它只需要知道如何将状态名称转换为实际状态。
我正在尝试使用 pact 来验证 spring 启动微服务。我已经从消费者生成了协议文件,并使用协议代理在提供者端对其进行了验证。
我有另一个用例,在根据实际服务响应验证协议文件之前,我需要执行一些代码。我阅读了有关状态更改 URL 和关闭状态更改以实现它的信息,但无法获得如何实现此目的的示例。有人可以帮忙吗?
我的具体情况是:我创建了一个合同来更新ID为1234的客户(名字:测试姓氏:用户)。
如果这个客户不存在,那么我需要通过从契约文件中的更新请求中读取名字、姓氏、id 和附加信息(城市、州、phone 号)通过状态更改代码。
所以我的问题是,我可以通过状态更改从 pact 文件中读取请求数据,而不是在验证端配置名字、姓氏和 ID 吗?
状态更改 URL 是您在提供程序上创建的一个挂钩,它允许 Pact 告诉提供程序它在测试开始时应该处于什么状态。在每次测试运行之前,模拟消费者在您的提供者上点击状态更改 URL,并告诉它测试期望的状态名称。
你需要做两件事:
- 配置状态更改URL
- 在提供程序上实施状态更改端点
配置状态更改URL
您可以在提供商验证设置中配置状态更改 URL。例如,使用 the maven plugin:
<serviceProvider>
<name>provider1</name>
<stateChangeUrl>http://localhost:8080/tasks/pactStateChange</stateChangeUrl>
...
hasPactWith('consumer1') {
stateChangeUrl = url('http://localhost:8080/tasks/pactStateChange')
...
这两个都告诉模拟消费者使用 localhost:8080/tasks/pactStateChange
在每次测试之前更改提供者的状态。
实现状态改变端点
上面链接的文档告诉我们,默认情况下,请求的格式是 POST 您的状态字符串和任何参数的请求:
{ "state" : "a provider state description", "params": { "a": "1", "b": "2" } }
要使用它,您需要在提供程序上实现类似以下未经测试的代码:
@RequestMapping(value = "tasks/pactStateChange", method = RequestMethod.POST)
ResponseEntity<?> stateChange(@RequestBody ProviderState state) {
if (state.state == "no database") {
// Set up state for the "no database" case here
} else if state.state == "Some other state" {
// Set up state here
} else if ... // Other states go here
...
}
return ResponseEntity.ok().build()
}
请原谅该示例中的任何 spring 引导错误 - 我不是 spring 引导人员,但您可以看到一般原则。
随着状态的改变 URL,pact 不会告诉提供商任何设置细节。它只是告诉提供者您在测试中使用的预先商定的状态字符串。这可能类似于 "foo exists"
。然后,在实现状态更改 URL 的处理程序时,您会检测到 "foo exists"
,并在那里进行任何显式设置。
if (state.state == "foo exists") {
// do whatever you need to set up so that foo exists
repository.clear()
repository.insert(new Foo("arguments that foo needs",12))
}
如果您想了解有关提供者状态的更多信息,请阅读 wiki page on provider states。
如何根据您的具体情况执行此操作
您问的是:
Can i read the request data from pact file through state change instead of configuring the first name,last name and id in the verification side?
您可能对合同测试的意图感到困惑 - 每个测试都是状态和请求的组合。
所以不用一个测试来表示:
- 我的测试是请求客户更新。如果客户存在,那么我期望 X 响应,如果不存在,那么我期望 Y 响应
你用两个测试说:
当我向客户记录提交更新时(在客户存在的状态下),那么我期望X响应。
当我提交更新客户记录时(在客户不存在的状态下),那么我期望Y响应。
这些测试是您的 Pact 合同中的两个独立项目。
目的是不在合同中包含设置的详细信息。在消费者方面,您的状态只是一个字符串,类似于 "Customer with id=1234 exists".
在提供商端,您的状态更改端点会检测到 URL 并根据需要创建状态。这通常以硬编码的方式完成:
if (state == "Customer with id=1234 exists") {
Database.Clear()
Database.Insert(new Customer(1234, "John","Smith"))
} else if (state == "No customers exist") {
Database.Clear()
}
您不想通过解析状态字符串以参数化的方式执行此操作,因为那样您将在测试消费者和提供者之间创建一个新的复杂合同。
消费者测试不应该知道如何设置提供者状态,他们应该只知道测试需要什么状态(仅按名称)。同样,提供者不需要知道正在测试什么,它只需要知道如何将状态名称转换为实际状态。