2

我正在为我的合同测试套件使用Pact gem(并且喜欢它!)。我正在测试的 API 服务需要所有请求的授权令牌。

我知道如何为我的用户生成 API 令牌,但我不知道在 Pact 工作流程中放置令牌的位置。我在 Pact 文档和 repo 中搜索了示例,但没有任何运气。

我尝试在消费者规范中发送 POST 以生成令牌,但 Pact 模拟服务器不知道如何处理请求和错误(如我所料)。

我发现了这个例子requestFilter,它看起来很有希望,特别是能够使用 a和方法为所有请求分配预定义的标头addHeader

如何在 Pact gem 中使用这样的请求过滤器?

如果这不是当前功能,我还有什么替代方案?

更新:

J_A_X 的答案非常适合与模拟服务器创建协议,但它不能满足 API 服务提供商对有效身份验证令牌的期望。更具体地说,我需要在运行 pact:verify 时将有效的身份验证令牌动态插入到协议中。所以,更近了一步,但仍然需要弄清楚后半部分。

马修的回答包含对后半部分(pact:verify)的两种可能解决方案的提示。我犹豫是否要引入另一个依赖项,所以我很想让 ProxyApp 类示例正常工作。我不明白我到底会传递给 ProxyApp.new() 什么。建议?

4

2 回答 2

1

实际上,除非您确实想要/需要,否则您实际上不必为每个协定交互使用真正的令牌。

通常对于那种东西,我只是创建一个正则表达式,用于在标题上验证某些规则,同时保持它“开放”。在我的节点项目(它在后面使用 Ruby 二进制文件)中,我创建了这 2 个实用程序函数来创建具有模式的对象和另一个用于对象最小值相等的对象:

function term(matcher, generate) {
    if ((typeof matcher === 'undefined') || (typeof generate === 'undefined')) {
      throw 'Matcher and Generate arguments must be specified to use Term';
    }
    return {
      "json_class": "Pact::Term",
      "data": {
        "generate": generate,
        "matcher": {
          "json_class": "Regexp",
          "o": 0,
          "s": matcher
        }
      }
    };
  }

  function somethingLike(value) {
    return {
      "json_class": "Pact::SomethingLike",
      "contents": value
    };
  }

然后,您可以在 DSL 定义中使用它,如下所示:

mockService
      .given('a form')
      .uponReceiving('a GET request with a valid auth')
      .withRequest('get', '/', term('^Bearer (?!null$).+$', 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ'))
      .willRespondWith({
        status: 200,
        headers: {'Content-Type': 'application/json;charset=utf-8'},
        body: {worked:true}
      });

'term' 实用程序有一个正则表达式作为第一个参数,然后是一个示例(应该与第一个参数匹配)在测试期间使用什么。

我知道这需要在 Pact 本身内更好地扩展,以使其更易于使用。我希望这有帮助。

于 2016-11-24T03:55:31.233 回答
1

根据 JVM 实现,Pact 的 Ruby 实现不直接支持这一点。

如果您使用的是 Pact Provider Proxy gem,您可以查看https://github.com/realestate-com-au/pact/issues/49#issuecomment-65346357https:/中讨论的一些选项/groups.google.com/forum/#!topic/pact-support/tSyKZMxsECk

一个示例可能类似于:

class ProxyApp

  def initialize real_app
    @real_app = real_app
  end

  def call env
    @real_app.call(env.merge('HTTP_AUTHORIZATION' => '12345'))
  end
end

Pact.service_provider "Some Provider" do
  app do
    ProxyApp.new(RealApp)
  end

  honours_pact_with "Some Consumer" do
    #...
  end
end
于 2016-11-24T21:36:39.090 回答