0

A server I need to integrate with returns its answers encoded as a JWT. Worse, the response body actually is a json, of the form:

{d: token} with token = JWT.encode({id: 123, field: "John", etc.})

I'd like to use a pact verification on the content of the decoded token. I know I can easily have a pact verifying that I get back a {d: string}, I can't do an exact match on the string (as the JWT contains some varying IDs). What I want is the following, which presumes the addition of a new Pact.JWT functionality.

my_provider. upon_receiving('my request') .with(method: :post, path: '/order', headers: {'Content-Type' => 'application/json'} ).will_respond_with( status: 200, headers: {'Content-Type' => 'application/json; charset=utf-8'}, body: { d: Pact::JWT( { id: Pact.like(123), field: Pact.term(generate: "John", matcher: /J.*/ },signing_key,algo ) })

Short of adding this Pact::JWT, is there a way to achive this kind of result?

I am already using the pact proxy to run my verification. I know you can modify the request before sending it for verification (How do I verify pacts against an API that requires an auth token?). Can you modify the request once you receive it from the proxy server?

If that's the case, I can plan for the following work around:

  • a switch in my actual code to sometimes expect the answers decoded instead of in the JWT
  • run my tests once with the swich off (normal code behaviour, mocks returns JWT data encoded.
  • run my tests a second time with the swich off (code expect data already decoded, mocks return decoded data.)
  • use the contract json from this second run
  • hook into the proxy:verify task to decode the JWT on the fly, and use the existing pact mechanisms for verification. (Step that I do not know how to do).

My code is in ruby. I do not have access to the provider.

Any suggestions appreciated! Thanks

Community
  • 1
  • 1
André
  • 1

2 Answers2

1

You can modify the request or response by using (another) proxy app.

class ProxyApp

  def initialize real_provider_app
    @real_provider_app = real_provider_app
  end

  def call env
    response = @real_provider_app.call(env)
    # modify response here
    response
  end
end

Pact.service_provider "My Service Provider" do
  app { ProxyApp.new(RealApp) }
end
Beth Skurrie
  • 1,333
  • 7
  • 8
  • 1
    The Pact.service_provider goes into the provider code (if any), and needs a require 'pact/provider' For Rails, the app is defined in config/application, where you have module MyAppName class Application, you'll want MyAppName::Application This answers it, though I'm not using it, rather, I've forked pact-support to add support for a Pact.Jwt object. – André May 23 '17 at 07:26
0

Pact as a tool, I don't expect it to give this behavior out of the box.

In my opinion, the best is,

  • Do not change source code only for tests
  • Make sure your tests verifies encoded json only (generate encoded expected json in test & verify that with actual)
Gopinath Langote
  • 311
  • 4
  • 10