这里是我的用例:
我的服务是: ServiceA。
它依赖于以下服务: ServicesB和ServiceC。
ServiceA向ServiceB发送一个POST请求,其中包含一些身份验证细节(username+password),而ServiceB则返回一个具有sessionId的json文档。
请求:
POST /authenticate
{
"username": "_at_api",
"password": "xxx"
}响应:
{
"sessionId": "axy235da7ad5a24abeb3e7fbb85d0ef45f"
}上面的sessionId用于从ServiceA到ServiceC的所有api调用。
ServiceA请求serviceC使用POST请求启动作业,serviceC返回作业id(字母数字)。
请求:
POST /jobs/local/start
Header: Authentication: axy235da7ad5a24abeb3e7fbb85d0ef45f
{
...
}响应:
{
"status": "RUNNING",
"jobId": "a209016e3fdf4425ea6e5846b8a46564abzt"
}ServiceA一直使用上面返回的serviceC来轮询作业的完成情况:
请求:
GET /jobs/status/a209016e3fdf4425ea6e5846b8a46564abzt
Header: Authentication: axy235da7ad5a24abeb3e7fbb85d0ef45f响应:
{
"status": "RUNNING"
}轮询将继续进行,直到状态返回为已完成或失败为止。
响应:
{
"status": "COMPLETED"
}如何使用协约测试serviceA?
我的计划是只使用单元测试和契约测试来实现90%以上的代码覆盖率。这是个好主意,还是我需要使用虚拟服务器进行单独的测试?我的理解是,契约是虚拟服务器(例如:坐骑银行)的超集,而虚拟服务器可以做的任何事情,契约都可以做到。因此,我不需要单独的组件测试。而且,看起来合同测试完全取代了端到端的测试,所以我也不需要端到端的测试。是这样的吗?
发布于 2017-12-28 01:53:22
而且,看起来合同测试完全取代了端到端的测试,所以我也不需要端到端的测试。是这样的吗?
不是的。合同测试不是功能测试(请参阅这篇优秀的文章,标题相同)
什么是合同测试?
契约测试是关于测试两个组件是否能够进行通信。
考虑一所房子和一名邮递员之间的合同:邮递员需要知道他们可以上门投递邮件(有时他们可能无法做到这一点--也许邮箱已经满了)。
从邮政工人的角度来看,合同如下:
请注意,邮政工作人员对邮筒的实现一无所知。可能有多种原因导致投递邮件失败--也许门被卡住了,可能箱子已经满了,也许邮件太大了,无法装进去。
在这种假设的情况下,我们的邮政工作人员在这些情况下并没有做什么不同的事情--他们只是没有交付。因此,从合同的角度来看,失败的原因是无关紧要的。这份合同--工人可以试着发送邮件,并且他们可以成功或不成功--可以在不列举所有可能的失败原因的情况下进行测试。
有关更详细的示例,请参阅链接在上面一文,但要引用文章末尾的内容:
合同应该是关于捕获:
契约的一个非常好的特性是,您可以对多个契约进行测试,只对它们所依赖的通信进行测试。
请注意,消费者契约测试只描述消费者需要进行或理解的通信。契约不一定是完整的API描述。
好吧,但是为什么我不能用合同测试来进行端到端的测试呢?
可以使用像契约这样的工具来代替您的端到端测试。然而,尽管合同测试与端到端测试所需的特性有很多相似之处,但合同测试(尤其是契约测试)并不是为端到端测试设计的。
如果您通过扩展现有的用户测试来进行端到端的测试(例如,将所有失败的原因添加到后期工作人员的测试中),那么合同意味着什么就不再清楚了。合同现在描述了通信是如何与行为一起进行的。
当您开始添加更多的消费者(例如,包裹快递员)时,这会导致问题--您是在所有消费者中复制所有的故障案例,还是将它们保留在最初的消费者测试中?如果您复制了测试,那么如果您更改了提供者的行为,那么您需要更改的东西很多--而您的测试将是脆弱的。如果你不重复测试,那么你的端到端测试就会被困在一个消费者身上--如果你解除了这个用户的功能,就会有失去测试的所有问题。
使用纯合同测试,如果要添加消费者已经理解的更多可能的失败原因,则(理想情况下)不必更改任何内容。
如果您尝试这样做,还有很多其他原因会让您头疼(您的测试开始严重依赖于精确的数据,如果您的测试是端到端的测试,那么失败的验证和我能部署挂钩的含义就会改变),但关键的是,契约并不是作为端到端测试的替代品而设计的。您可以这样使用它,但这是不可取的,并可能导致痛苦的维护。
我如何使用契约测试serviceA?
您可以分别描述每个请求,使用Pact提供者状态作为每个请求的先决条件。
此外,您可能会发现关于协议-使用提供程序状态的问题很有帮助。
发布于 2020-07-08 13:34:16
虽然这件事来得很晚,但对于所有偶然发现这件事的人来说:
pact规范(v3.0)只支持每个交互的一个请求(但是每个使用者-提供者-对支持多个交互)。在提供程序方面,每次交互都会产生一个单独的测试。因此,虽然在提供程序端运行序列或请求在概念上不是一个好主意,但它在技术上也不起作用。
然而,在消费者方面,你有一个选择--我鼓励你不要在端到端测试中误用。在我的例子中,我有一个类,它实现了一个包含多个请求的模板/策略模式,并且不允许在使用者端注入中间状态。它要求所有请求都有有效的答复。
在这种情况下,pact-jvm-consumer-junit (=JUnit4 4)允许在单个测试方法上指定多个PactVerification注释(在我的例子中是Kotlin):
@Test
@PactVerifications(
value = [
PactVerification("Service B", fragment = "authenticateOk"),
PactVerification("Service C", fragment = "jobStartOk")
PactVerification("Service C", fragment = "jobStatusOk")
]
)
fun `test successful job execution`() {
// add your test here.
}在提供程序端,上面的所有片段都作为单独的测试执行,因此它们需要一个正确的状态,如上面的答案所指定的那样。
我在JUnit4中运行了这种方法。不过,JUnit5还没有找到一种快速的方法来模仿它。
https://stackoverflow.com/questions/47976094
复制相似问题