这是我的用例:
我的服务是:服务。 它取决于以下服务:服务和服务。
ServiceA向Service发送POST请求,其中包含一些身份验证详细信息(用户名+密码),ServiceS使用具有sessionId的json文档回复。
请求:
POST /authenticate
{
"username": "_at_api",
"password": "xxx"
}
响应:
{
"sessionId": "axy235da7ad5a24abeb3e7fbb85d0ef45f"
}
上面的sessionId用于从Service到Service的所有api调用。
ServiceA请求serviceS使用POST请求启动作业,并且服务返回作业ID(字母数字)。
请求:
POST /jobs/local/start
Header: Authentication: axy235da7ad5a24abeb3e7fbb85d0ef45f
{
...
}
响应:
{
"status": "RUNNING",
"jobId": "a209016e3fdf4425ea6e5846b8a46564abzt"
}
ServiceS使用上面返回的jobId保持轮询服务以完成作业:
请求:
GET /jobs/status/a209016e3fdf4425ea6e5846b8a46564abzt
Header: Authentication: axy235da7ad5a24abeb3e7fbb85d0ef45f
响应:
{
"status": "RUNNING"
}
轮询继续,直到状态返回为COMPLETED或FAILED。
响应:
{
"status": "COMPLETED"
}
如何使用Pact测试服务?
我的计划是仅使用单元测试和合同测试来实现超过90%的代码覆盖率。这是一个好主意,还是我需要使用虚拟服务器进行单独的测试?我的理解是Pact是虚拟服务器的超集(例如:mountebank)以及虚拟服务器可以做的所有事情,Pact可以做到。所以我不需要单独的组件测试。此外,看起来合同测试完全取代了端到端测试,因此我也不需要端到端测试。这是正确的吗?
此外,看起来合同测试完全取代了端到端测试,因此我也不需要端到端测试。这是正确的吗?
合同测试不是功能测试(参见this excellent article, with the same title)
合同测试是关于测试两个组件是否能够通信。
考虑一个房子和一个邮政工人之间的合同:邮政工人需要知道他们可以接近房子并发送邮件(有时他们可能无法做到这一点 - 也许邮箱已满)。
从邮政工人的角度来看,合同如下:
请注意,邮政工作人员对邮箱的实施一无所知。也许有多种原因导致邮箱发送可能会失败 - 可能是门被堵塞,也许箱子已经满了,也许邮箱太大而不适合它。
在这个假设的案例中,我们的邮政工作人员在这些情况下没有做任何不同的事情 - 他们只是无法提供。因此,从合同的角度来看,失败的原因是无关紧要的。合同 - 工人可以尝试交付帖子,并且他们可以成功或不成功 - 可以在不列举所有可能的失败原因的情况下进行测试。
有关更详细的示例,请参阅文章linked above,但引用它的结尾:
合同应该是关于捕捉:
- 消费者中的错误
- 消费者对终点或有效负载的误解
- 中断提供者对端点或有效负载的更改
Pact的一个非常好的功能是,您可以仅针对他们所依赖的通信测试多个合同。
请注意,消费者合同测试仅描述消费者需要制作或理解的通信。合同不是(必然)完整的API描述。
可以使用像Pact这样的工具来替换您的端到端测试。但是,尽管合同测试与端到端测试所需的功能有很多相似之处,但合同测试(特别是Pact)并非设计用于端到端测试。
如果您通过扩展现有消费者的测试(例如,将所有可能的原因添加到后期工作者的测试中)来进行端到端测试,那么合同意味着什么就不再清楚了。合同现在描述了通信如何与行为一起工作。
当您开始添加更多消费者(例如,包裹快递)时,这会导致问题 - 您是否复制了所有消费者中的所有失败案例,或者您是否只是将其保留在原始的消费者测试中?如果您复制测试,那么如果您更改提供程序的行为,则需要更改许多内容 - 并且您的测试将会很脆弱。如果您没有复制测试,那么您的端到端测试将停留在一个消费者身上 - 如果您淘汰该消费者,则会遇到丢失问题的所有问题。
通过纯合同测试,您(理想情况下)如果您正在添加消费者已经理解的更多可能的失败原因,则无需进行任何更改。
如果你尝试这个,你会有很多其他的原因让你头痛(你的测试开始严重依赖于确切的数据,如果你的测试是端到端的测试,那么失败的验证和can-i-deploy钩子的含义会改变),但是关键的一点是,Pact不是为了替代端到端测试而设计的。你可以这样使用它,但这是不可取的,并可能导致痛苦的维护。
您可以使用Pact provider state作为每个请求的先决条件单独描述每个请求。
此外,您可能会发现有关PACT - Using provider state的问题很有帮助。