大约半年前,我的组织开始使用Pact来创建/验证用Java编写的REST服务/微服务之间的合同.我们很难决定提供商测试的适当范围或把握应该是什么,并且会喜欢其他协议用户的经验.
基本上,讨论围绕提供程序测试中的mock/stub的位置进行演变.在服务中,您必须至少模拟对其他服务的外部调用,但您也可以选择模拟更接近REST资源类.
我们将其归结为两种选择:
1.第一个选项是提供者测试应该是严格的合同测试,并且只运用提供者服务的REST资源类,模拟/删除从那里使用的服务类/协调器等.此合同测试将通过组件测试进行扩充,该组件测试将测试由提供程序测试存根/模拟的部件.
2.第二个选项是使用提供程序测试作为组件测试,该测试将为每个请求执行整个服务组件.只有对其他组件的传递外部调用才会被模拟/存根.
这些是每个选项的专业人士的想法
选项1的专业版:
选项2的专业版:
我真的很想知道您的提供商测试通常在这方面的看法.有最好的做法吗?
澄清"组件"的含义:组件是微服务或更大服务应用程序中的模块.我们采用了来自Martin Fowlers的组件的定义http://martinfowler.com/articles/microservice-testing/.
提供者服务/组件通常在Jersey资源类中具有REST端点.此端点是Pact提供程序测试的提供程序端点.一个例子:
@Path("/customer")
public class CustomerResource {
@Autowired private CustomerOrchestrator customerOrchestrator;
@GET
@Path("/{customerId}")
@Produces(MediaType.APPLICATION_JSON)
public Response get(@PathParam("customerId") String id) {
CustomerId customerId = CustomerIdValidator.validate(id);
return Response.ok(toJson(customerOrchestrator.getCustomer(customerId))).build();
}
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,@ Aututired(我们使用spring)CustomerOrchestrator可以在运行提供程序测试时进行模拟,也可以注入真正的"Impl"类.如果您选择注入真正的"CustomerOrchestratorImpl.class",它将具有额外的@Autowired bean依赖项,而这些依赖项又可能具有其他...等等.最后,依赖项将最终出现在将进行数据库调用的DAO对象中,或者一个REST客户端,它将对其他下游服务/组件执行HTTP调用.
如果我们在上面的例子中采用我的"选项1"解决方案,我们将模拟CustomerResource中的customerOrchestrator字段,如果我们采用"选项2",我们将为CustomerResource中的每个依赖项注入Impl类(真实类)依赖图并创建模拟的数据库条目和模拟下游服务.
作为旁注,我应该提到我们很少在提供程序测试中实际使用真实数据库.在我们采用"选项2"的情况下,我们模拟了DAO类层,而不是模拟实际的数据库数据,以减少测试中移动部件的数量.
我们创建了一个"测试框架",可以自动模拟任何未在spring上下文中显式声明的Autowired依赖项,因此stubing/mocking对我们来说是一个轻量级的过程.这是运行CustomerResource并启动存根的CustomerOrchestrator bean的提供程序测试的摘录:
@RunWith(PactRunner.class)
@Provider("customer-rest-api")
@PactCachedLoader(CustomerProviderContractTest.class)
public class CustomerProviderContractTest {
@ClassRule
public static PactJerseyWebbAppDescriptorRule webAppRule = buildWebAppDescriptorRule();
@Rule
public PactJerseyTestRule jersyTestRule = new PactJerseyTestRule(webAppRule.appDescriptor);
@TestTarget public final Target target = new …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一项契约消费者测试以匹配以下响应。
[
{
"accountId" : 1,
"permissions" : [
{
"schedule" : {
"01/01/2018" : false,
"01/01/1900" : true
},
"permissionId" : 3
}
]
}
]
Run Code Online (Sandbox Code Playgroud)
每个调度对象都由与简单正则表达式匹配的未知数量的键组成。但是我没有看到一种使用正则表达式匹配键同时将值映射到简单布尔值的方法。
例如,我在API中看到以下方法。
public LambdaDslObject eachKeyLike(
String exampleKey,
Consumer<LambdaDslObject> nestedObject)
Run Code Online (Sandbox Code Playgroud)
但这将期望一个新对象作为值,而不是原始类型。
"schedule" : {
"01/01/2018" : { ... }, // not what I want to match
"01/01/1900" : false // what I want to match
}
Run Code Online (Sandbox Code Playgroud)
有没有办法在pact-jvm中指定映射到原始值的不精确键?
我对是否应该考虑某种类型的测试功能或合同有疑问。
假设我有一个像 /getToolType 这样的 API,它接受一个 {object" "myObject"} 作为输入,并以 {type: "[az]+"} 的形式返回 type
客户端和服务器之间一致认为返回的类型将匹配一组字符串,比如 [hammer|knife|screwdriver],所以消费者决定在枚举中解析它们,当返回的类型未知时使用回退值。
消费者是否应该为每种类型(锤子、刀子、螺丝刀)包含一个测试用例,以确保生产者仍然遵守它总是返回的协议,例如,当使用锤子对象调用 /getToolType 时,小写字符串“hammer” ? 或者你会认为这样的测试用例是功能性的吗?为什么?
有人可以详细指出如何逐步将 JSON 协议发布到 Pact Broker 吗?
已安装 docker、dius/pack_broker 和 Postgres(brew 安装)。
缺少以正确的方式修复上述所有内容的要点,以及将 JSON 协议发布到协议代理的适当脚本。
补充一下,我在消费者端使用 JVM 实现。以及提供者端的简单 gradle 验证。