如何在持久服务和同步无服务器功能之间定义契约合同?

时间:2019-07-10 12:06:40

标签: aws-lambda serverless-framework serverless pact

我有一个持久性服务,该服务使用一些输入同步调用无服务器功能(在AWS lambda上,通过serverless framework),无服务器(无状态)lambda函数对输入进行一些转换并同步进行将输出返回给呼叫服务。

我想写一个Pact contract,其中无服务器功能是提供者,而持久服务是使用者。我该如何针对synchronous(即RequestResponse)无服务器功能执行此操作?

我有found a few resources关于无服务器功能的协定,但是除非我误解了,否则它们似乎都只能解决异步用例。 需要明确的是,在本例中,用例不是异步的,事件驱动的消息传递,而是无服务器功能的同步调用,在等待响应时会阻塞。

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

在我的情况下,持久性服务(消费者)在Java中,而无服务器功能在Kotlin中,即在JVM上。

2 个答案:

答案 0 :(得分:1)

正如Matthew Fellows所提到的,您可以配置AWS Lambda Client来调用您的自定义URL,因为它在后台执行常规HTTP请求。使用AWSLambdaClientBuilder并执行:

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

您需要在请求标头中设置Content-Type: application/json,否则Pact无法解析标头(因为由于某种原因默认情况下默认为空字符串)。为此使用withRequestHandlers并通过此客户端调用lambda函数来创建消费者合同(它应请求Pact模拟服务器而不是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")
    }
}

答案 1 :(得分:0)

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

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

选项2(未试用)

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

请参见https://gist.github.com/bethesque/c858e5c15649ae525ef0cc5264b8477c,了解关于req / res风格的互动方式(并在slack.pact.io上加入我们以进行聊天)