2016-11-24 64 views
2

我为我的合同测试套件使用了Pact宝石(并且非常喜欢!)。我要测试的API服务需要所有请求的授权令牌。如何针对需要身份验证令牌的API验证协议?

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

我试着在消费者规范中发送一个POST来生成一个令牌,但是Pact mock服务器不知道如何处理请求和错误(正如我所期望的那样)。

我发现this example它看起来很有希望,特别是能够使用requestFilteraddHeader方法为所有请求分配预定义的标头。

我该如何使用Pact gem这样的请求过滤器?

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

UPDATE:

J_A_X's answer的伟大工程,为创建与模拟服务器的协定,但它不能满足一个有效的身份验证令牌的API服务提供商的期望。更具体地说,我需要在运行pact:verify时动态地将有效的认证令牌插入到协议中。所以,更近一步,但仍需要弄清楚后一部分。

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

回答

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中更好地扩展以使其更易于使用。我希望这有帮助。

+0

谢谢您的完整的答案!你的例子当然可以起作用,尽管它对我来说更像是一种解决方法。我希望有一种内置的方法可以让我用真正的认证令牌来验证协议。 – mycargus

+1

好吧,你可以使用它们,但这里的问题是你现在必须知道在创建交互之前该令牌将会是什么,然后对它们进行测试。我不知道如何轻松创建流程,而不会以某种方式作弊,这基本上与此相同。 最后,问问你自己这个特定的交互检查在你的提供者的整体测试中是否真的非常重要。在我看来,这不是,因此我的正则表达式;对我来说重要的是业务API以正确的格式/类型返回数据。 –

+0

您的方法非常适合与模拟服务器创建协议,但不符合API服务提供商对有效身份验证令牌的期望。更具体地说,我需要在运行pact:verify时动态地将有效的认证令牌插入到协议中。那有意义吗? – mycargus

1

Pact的Ruby实现不直接按照JVM实现支持此操作。

如果您使用的是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 
+0

我会考虑使用提供者代理。谢谢! – mycargus

+0

我现在看到您推荐两种不同的可能解决方案:(1)使用Pact提供程序代理来验证针对单独运行提供程序的协议,或者(2)使用提供程序的pact_helper.rb中的类来合并动态auth标头到协定核查。我正在尝试第二种方法。 – mycargus

+0

谢谢@mycargus,我很想听听你如何去。这可能是进入我们的文档的一个很好的例子,因为它偶尔会出现。 –