如何针对需要身份验证令牌的API验证协议?

时间:2016-11-24 03:13:15

标签: ruby pact pact-ruby

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

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

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

我找到了this example,这似乎很有希望,特别是能够使用requestFilteraddHeader方法为所有请求分配预定义的标头。

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

如果那不是当前功能,我还有哪些替代方案?

更新

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

Matthew's answer包含对后一部分似乎是两种可能解决方案的提示(pact:verify)。我不愿意引入另一个依赖项,所以我很想让ProxyApp类示例正常工作。我不明白我究竟会将什么传递给ProxyApp.new()。建议?

2 个答案:

答案 0 :(得分:1)

除非你真的想要/需要,否则你实际上不必为每个契约互动使用真实的令牌。

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

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}
      });

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

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

答案 1 :(得分: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