pact-foundation / pact-ruby

Enables consumer driven contract testing, providing a mock service and DSL for the consumer project, and interaction playback and verification for the service provider project.
https://pact.io
MIT License
2.17k stars 216 forks source link

Provider tests do not find route of interaction (404) #224

Closed hsaab closed 4 years ago

hsaab commented 4 years ago

Hello! I am trying to set up pact (1.32.0) in a rails app (v 4.2.11.3). I've gotten all the way to the point where I have the pact_helper.rb file setup and when running rake pact:verify, I can see the contract from the consumer is being tested against.

The issue I have is that I have the route of the interaction setup in my config/routes.rb file but I'm not sure why I'm getting a 404 in the test. It's almost like pact is telling me the route doesn't exist. I'll attach the relevant files below and any assistance would be much appreciated :)

Error I'm getting

hassan-mac:api hassansaab$ rake pact:verify
SPEC_OPTS='' /Users/hassansaab/.rvm/rubies/ruby-2.3.7/bin/ruby -S pact verify --pact-helper /Users/hassansaab/Coding/sweetgreen/gravy/lib/gravy/api/spec/contract/order_web/pact_helper.rb

Verifying a pact between order_web and gravy
  Given An order preview is received.
    A GET request to the order preview endpoint.
      with GET /api/orders/345890/preview
        returns a response which
          has status code 200 (FAILED - 1)
          has a matching body (FAILED - 2)
          includes headers
            "Content-Type" which equals "application/json" (FAILED - 3)

Failures:

  1) Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has status code 200
     Failure/Error: expect(response_status).to eql expected_response_status

       expected: 200
            got: 404

       (compared using eql?)
     # /Users/hassansaab/.rvm/gems/ruby-2.3.7/gems/pact-1.32.0/bin/pact:4:in `<top (required)>'
     # /Users/hassansaab/.rvm/gems/ruby-2.3.7/bin/pact:23:in `load'
     # /Users/hassansaab/.rvm/gems/ruby-2.3.7/bin/pact:23:in `<main>'

pact_helper.rb

require 'pact/provider/rspec'
require File.expand_path('../../dummy/config/environment', __dir__)
require Gravy::Api::Engine.root.join('spec/spec_helper.rb')
require Gravy::Api::Engine.root.join('spec/contract/order_web/provider_state_for_order_web.rb')

Pact.service_provider 'gravy' do
  app { Dummy::Application.new }

  honours_pact_with 'order_web' do
    pact_uri './api/spec/contract/order_web/order_web-gravy.json'
  end
end
config/routes.rb
module Gravy
  module Api
    Engine.routes.draw do
      scope module: :v1, constraints: Constraints.new(version: 1, default: true) do
        resources :orders do
          member do
            get :preview
          end
        end
      end
    end
  end
end
dummy/config/routes.rb
Rails.application.routes.draw do
  mount Gravy::Api::Engine => '/api'
end
contract/order_web-gravy.json
{
  "consumer": {
    "name": "order_web"
  },
  "provider": {
    "name": "gravy"
  },
  "interactions": [
    {
      "description": "A GET request to the order preview endpoint.",
      "providerState": "An order preview is received.",
      "request": {
        "method": "GET",
        "path": "/api/orders/345890/preview"
      },
      "response": {
        "status": 200,
        "headers": {
          "Content-Type": "application/json"
        },
         ...
        "body": {
          // body taken out for brevity
         }
}
Pact log file
# Logfile created on 2020-09-24 14:13:35 -0600 by logger.rb/56438
I, [2020-09-24T14:13:35.915340 #49663]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has status code 200'
I, [2020-09-24T14:13:35.916089 #49663]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has a matching body'
I, [2020-09-24T14:13:35.916447 #49663]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which includes headers "Content-Type" which equals "application/json"'
I, [2020-09-24T14:16:39.607632 #49721]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has status code 200'
I, [2020-09-24T14:16:39.608926 #49721]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has a matching body'
I, [2020-09-24T14:16:39.609312 #49721]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which includes headers "Content-Type" which equals "application/json"'
I, [2020-09-24T14:22:18.980536 #49823]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has status code 200'
I, [2020-09-24T14:22:18.981872 #49823]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has a matching body'
I, [2020-09-24T14:22:18.982150 #49823]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which includes headers "Content-Type" which equals "application/json"'
I, [2020-09-24T14:25:09.438394 #49909]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has status code 200'
I, [2020-09-24T14:25:09.439246 #49909]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T14:25:09.439302 #49909] DEBUG -- : body :
I, [2020-09-24T14:25:09.524315 #49909]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has a matching body'
I, [2020-09-24T14:25:09.524404 #49909]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T14:25:09.524428 #49909] DEBUG -- : body :
I, [2020-09-24T14:25:09.525032 #49909]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which includes headers "Content-Type" which equals "application/json"'
I, [2020-09-24T14:25:09.525079 #49909]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T14:25:09.525110 #49909] DEBUG -- : body :
I, [2020-09-24T14:31:34.111117 #50068]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has status code 200'
I, [2020-09-24T14:31:34.111707 #50068]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T14:31:34.111765 #50068] DEBUG -- : body :
I, [2020-09-24T14:31:34.190474 #50068]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has a matching body'
I, [2020-09-24T14:31:34.190585 #50068]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T14:31:34.190612 #50068] DEBUG -- : body :
I, [2020-09-24T14:31:34.191354 #50068]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which includes headers "Content-Type" which equals "application/json"'
I, [2020-09-24T14:31:34.191417 #50068]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T14:31:34.191439 #50068] DEBUG -- : body :
I, [2020-09-24T14:31:52.207240 #50084]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has status code 200'
I, [2020-09-24T14:31:52.207901 #50084]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has a matching body'
I, [2020-09-24T14:31:52.208145 #50084]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which includes headers "Content-Type" which equals "application/json"'
I, [2020-09-24T14:33:44.572460 #50134]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has status code 200'
I, [2020-09-24T14:33:44.572620 #50134]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T14:33:44.572647 #50134] DEBUG -- : body :
I, [2020-09-24T14:33:44.654301 #50134]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has a matching body'
I, [2020-09-24T14:33:44.654405 #50134]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T14:33:44.654453 #50134] DEBUG -- : body :
I, [2020-09-24T14:33:44.655151 #50134]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which includes headers "Content-Type" which equals "application/json"'
I, [2020-09-24T14:33:44.655203 #50134]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T14:33:44.655225 #50134] DEBUG -- : body :
I, [2020-09-24T14:56:52.785477 #50526]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has status code 200'
I, [2020-09-24T14:56:52.786012 #50526]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T14:56:52.786676 #50526] DEBUG -- : body :
I, [2020-09-24T14:56:52.864310 #50526]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has a matching body'
I, [2020-09-24T14:56:52.864415 #50526]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T14:56:52.864436 #50526] DEBUG -- : body :
I, [2020-09-24T14:56:52.865052 #50526]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which includes headers "Content-Type" which equals "application/json"'
I, [2020-09-24T14:56:52.865103 #50526]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T14:56:52.865122 #50526] DEBUG -- : body :
I, [2020-09-24T14:57:39.716227 #50549]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has status code 200'
I, [2020-09-24T14:57:39.717769 #50549]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has a matching body'
I, [2020-09-24T14:57:39.718203 #50549]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which includes headers "Content-Type" which equals "application/json"'
I, [2020-09-24T15:00:27.309320 #50635]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has status code 200'
I, [2020-09-24T15:00:27.309840 #50635]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T15:00:27.309879 #50635] DEBUG -- : body :
I, [2020-09-24T15:00:27.400553 #50635]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has a matching body'
I, [2020-09-24T15:00:27.400644 #50635]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T15:00:27.400666 #50635] DEBUG -- : body :
I, [2020-09-24T15:00:27.401292 #50635]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which includes headers "Content-Type" which equals "application/json"'
I, [2020-09-24T15:00:27.401352 #50635]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T15:00:27.401430 #50635] DEBUG -- : body :
I, [2020-09-24T15:05:21.919506 #50734]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has status code 200'
I, [2020-09-24T15:05:21.920425 #50734]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T15:05:21.920481 #50734] DEBUG -- : body :
I, [2020-09-24T15:05:22.004333 #50734]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has a matching body'
I, [2020-09-24T15:05:22.004415 #50734]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T15:05:22.004434 #50734] DEBUG -- : body :
I, [2020-09-24T15:05:22.007994 #50734]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which includes headers "Content-Type" which equals "application/json"'
I, [2020-09-24T15:05:22.008061 #50734]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T15:05:22.008079 #50734] DEBUG -- : body :
I, [2020-09-24T15:05:32.557821 #50741]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has status code 200'
I, [2020-09-24T15:05:32.557946 #50741]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T15:05:32.557972 #50741] DEBUG -- : body :
I, [2020-09-24T15:05:32.622390 #50741]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has a matching body'
I, [2020-09-24T15:05:32.622478 #50741]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T15:05:32.622500 #50741] DEBUG -- : body :
I, [2020-09-24T15:05:32.625765 #50741]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which includes headers "Content-Type" which equals "application/json"'
I, [2020-09-24T15:05:32.625818 #50741]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T15:05:32.625838 #50741] DEBUG -- : body :
I, [2020-09-24T15:10:45.660578 #50831]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has status code 200'
I, [2020-09-24T15:10:45.661338 #50831]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T15:10:45.661395 #50831] DEBUG -- : body :
I, [2020-09-24T15:10:45.751838 #50831]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has a matching body'
I, [2020-09-24T15:10:45.751925 #50831]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T15:10:45.751951 #50831] DEBUG -- : body :
I, [2020-09-24T15:10:45.755759 #50831]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which includes headers "Content-Type" which equals "application/json"'
I, [2020-09-24T15:10:45.755836 #50831]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T15:10:45.755861 #50831] DEBUG -- : body :
I, [2020-09-24T15:51:34.075953 #51632]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has status code 200'
I, [2020-09-24T15:51:34.076766 #51632]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T15:51:34.076831 #51632] DEBUG -- : body :
I, [2020-09-24T15:51:34.162930 #51632]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which has a matching body'
I, [2020-09-24T15:51:34.163030 #51632]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T15:51:34.163050 #51632] DEBUG -- : body :
I, [2020-09-24T15:51:34.166356 #51632]  INFO -- : Running example 'Verifying a pact between order_web and gravy Given An order preview is received. A GET request to the order preview endpoint. with GET /api/orders/345890/preview returns a response which includes headers "Content-Type" which equals "application/json"'
I, [2020-09-24T15:51:34.166405 #51632]  INFO -- : Sending GET request to path: "/api/orders/345890/preview" with headers: {}, see debug logs for body
D, [2020-09-24T15:51:34.166422 #51632] DEBUG -- : body :
bethesque commented 4 years ago

I would say your route doesn't exist :P

I haven't used Rails for many many years, so I'm not sure how much help I can provide. One thing I noticed is scope module: :v1,. Does that put a /v1 prefix in the route?

hsaab commented 4 years ago

haha. Thanks @bethesque, that's a good idea - I played a bit with different route combinations but turns out the original route was right.

The fix was not opting out of the config.ru and setting one up within the api directory (where rake pact:verify was run). If anyone runs in to the same issue, try to set up the config.ru first (as the docs describe)!

hsaab commented 4 years ago

I do have one question @bethesque . Is there a way to configure the config.ru path that pact looks for when running rake pact:verify? Couldn't find too much on that within the docs

bethesque commented 4 years ago

Yes, you can set the config.ru path on the configuration object

https://github.com/pact-foundation/pact-ruby/blob/master/lib/pact/provider/configuration/configuration_extension.rb#L28

This line here shows how you can parse the app out of the config.ru file https://github.com/pact-foundation/pact-ruby/blob/55bb93584b26619952bd251a0e8fe079f39555a7/lib/pact/provider/configuration/service_provider_dsl.rb#L24

hsaab commented 4 years ago

Thank you for your help! @bethesque