消费者驱动契约:按消费者存根
在某些情况下,同一个端点的两个消费者可能需要两种不同的响应。
这种方法还能让你立刻知道哪个消费者使用了你 API 的哪一部分。你可以移除 API 生成的响应中的某一部分,然后观察哪些自动生成的测试会失败。如果没有测试失败,你就可以安全地删除响应的那部分,因为没有人使用它。
考虑以下为名为 producer 的生产者定义的合约示例,该合约有两个消费者(foo-consumer 和 bar-consumer):
request {
url '/foo'
method GET()
}
response {
status OK()
body(
foo: "foo"
}
}
request {
url '/bar'
method GET()
}
response {
status OK()
body(
bar: "bar"
}
}
你不能为同一个请求生成两种不同的响应。这就是为什么你可以正确地打包合约,然后利用 stubsPerConsumer 功能来获益。
在生产者端,消费者可以拥有一个仅包含与其相关契约的文件夹。通过将 spring.cloud.contract.stubrunner.stubs-per-consumer 标志设置为 true,我们将不再注册所有存根,而只注册那些与消费者应用程序名称对应的存根。换句话说,我们会扫描每个存根的路径,只有当路径中包含以消费者名称命名的子文件夹时,才会注册该存根。
在 foo 生产者端,合约将如下所示
.
└── contracts
├── bar-consumer
│ ├── bookReturnedForBar.groovy
│ └── shouldCallBar.groovy
└── foo-consumer
├── bookReturnedForFoo.groovy
└── shouldCallFoo.groovy
bar-consumer 消费者可以设置 spring.application.name 或 spring.cloud.contract.stubrunner.consumer-name 为 bar-consumer。或者,你也可以按如下方式设置测试:
@SpringBootTest(classes = Config, properties = ["spring.application.name=bar-consumer",
"spring.cloud.contract.stubrunner.jms.enabled=false"])
@AutoConfigureStubRunner(ids = "org.springframework.cloud.contract.verifier.stubs:producerWithMultipleConsumers",
repositoryRoot = "classpath:m2repo/repository/",
stubsMode = StubRunnerProperties.StubsMode.REMOTE,
stubsPerConsumer = true)
@ActiveProfiles("streamconsumer")
@Disabled("TODO: Sth wrong with stream?")
class StubRunnerStubsPerConsumerSpec {
...
}
那么,只有注册在名称包含 bar-consumer 的路径下的存根(即来自 src/test/resources/contracts/bar-consumer/some/contracts/… 文件夹的那些)才允许被引用。
你也可以显式设置消费者名称,如下所示:
@SpringBootTest(classes = Config, properties = "spring.cloud.contract.stubrunner.jms.enabled=false")
@AutoConfigureStubRunner(ids = "org.springframework.cloud.contract.verifier.stubs:producerWithMultipleConsumers",
repositoryRoot = "classpath:m2repo/repository/",
consumerName = "foo-consumer",
stubsMode = StubRunnerProperties.StubsMode.REMOTE,
stubsPerConsumer = true)
@ActiveProfiles("streamconsumer")
@Disabled("TODO: Sth wrong with stream?")
class StubRunnerStubsPerConsumerWithConsumerNameSpec {
...
}
那么,只有注册在路径名包含 foo-consumer 下的存根(即来自 src/test/resources/contracts/foo-consumer/some/contracts/… 文件夹的那些)才允许被引用。
有关此变更背后原因的更多信息,请参阅 issue 224。