如何在持久服务和同步无服务器函数之间定义 Pact 契约?

How to define a Pact contract between a persistent service and a synchronous serverless function?

我有一个持久化服务,它使用一些输入同步调用无服务器函数(在 AWS lambda, via the serverless framework 上),无服务器(和无状态)lambda 函数对输入执行一些转换并同步 returns输出回调用服务。

我想写一个 Pact contract where the serverless function is the provider and the persistent service is the consumer. How can I do this for a synchronous (i.e. RequestResponse) 无服务器函数?

我有 found a few resources 无服务器函数协议,但它们似乎都只处理异步用例,除非我误解了什么。 需要明确的是,我的用例不是异步的、事件驱动的消息传递,而是同步调用无服务器函数,在等待响应时阻塞。

从Pact文档中,我发现references只支持基于HTTP的API和基于消息的异步API。这个用例不适合这两种模式,因为我们使用无服务器框架,它在幕后执行实际的 HTTP 请求。

就我而言,持久服务(消费者)在 Java 中,无服务器功能在 Kotlin 中,即都在 JVM 中。

这是 Pact 尚未直接支持的内容。

选项 1 目前,您需要编写两组独立的测试来涵盖交互的请求和响应方面,一组由消费者发起,另一组由提供者发起。

选项 2(未测试)

调用 lambda 只是通过 AWS lambda 服务的 HTTP POST 请求,因此理论上可以通过常规 HTTP request/response 对其进行测试。

请参阅 https://gist.github.com/bethesque/c858e5c15649ae525ef0cc5264b8477c 了解有关 req/res 风格交互的一些想法(并加入我们 slack.pact.io 讨论)

如 Matthew Fellows 所述,您可以配置 AWS Lambda Client to invoke your custom URL since it does regular HTTP request under the hood. Use AWSLambdaClientBuilder 并执行:

withEndpointConfiguration(
 AwsClientBuilder.EndpointConfiguration(pactMockServerEndpoint, Regions.EU_CENTRAL_1.name)
)

您需要在请求 header 中设置 Content-Type: application/json 否则 Pact 无法解析 header (因为由于某种原因它默认为空字符串)。为此使用 withRequestHandlers 并通过此客户端调用 lambda 函数来创建消费者合约(它应该请求 Pact mock-server 而不是 AWS)。

但是,在生产者方面,您需要:

  • 创建代理服务器(使用类似MockServer的东西)
  • 在 运行 Pact 测试时使用 Pact JUnit provider 以便您可以启动代理服务器
  • 像平常一样玩 Pact 合约时使用 HTTP 目标并将代理设置为目标

想法是您有一个使用无服务器处理函数返回响应的代理 HTTP 服务器:

mockServer.`when`(
    HttpRequest.request().withPath(".*")
).respond { httpRequest ->
    HttpResponse.response(
        // Invoke handler and return response
        OBJECT_MAPPER.writeValueAsString(invokeLambdaWithRequest(httpRequest))
    ).let { httpResponse ->
        httpResponse.withHeader(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8")
    }
}