ED209
ED209

Reputation: 638

PACT-JS - Provider contract verification error/failure - PactFlow

I am pulling my hair out. I have created a Pact-JS test framework to test my simple NodeJS application. I will show all the code below. I have used PactFlow to host my contract document (which was generated by running my consumer test). The problem is When I run my provider code it is failing. I get the following error (I will post the more verbose error below)) - `assert_success!': Error retrieving https://zaizi.pactflow.io/pacts/provider/Clients%20Service/for-verification status=404

Consumer test code - pact.consumer.spec.js

const { Matchers, Publisher } = require("@pact-foundation/pact")
const Pact = require("@pact-foundation/pact").Pact
const { getClients, getClient, postClient } = require("../../src/consumer")
const path = require("path")

// mock provider setup
const mockProvider = new Pact({
    port: 8081,
    log: path.resolve(process.cwd(), "__tests__/logs", "mock-provider.log"), // log file location and name
    dir: path.resolve(process.cwd(), "__tests__/pacts"), // location where pact contract will be saved
    spec: 2,
    logLevel: 'INFO',
    pactfileWriteMode: "overwrite",
    consumer: "pact-consumer",
    provider: "pact-provider"
 })

 describe("Pact for Clients Service API", () => {
    beforeAll(() => mockProvider.setup());  // Start the Mock Server and wait for it to be available
    afterEach(() => mockProvider.verify()); // Verifies that all interactions specified
    afterAll(() => mockProvider.finalize()); // Records the interactions between the Mock Server into the pact file and shuts it down


    describe('given there are clients', () => {
        describe('when a request is made to GET all clients', () => {

            // GET_EXPECTED_BODY = [
            //     { "firstName": "Lisa", "lastName": "Simpson", "age": 8, "id": 1 }, 
            //     { "firstName": "Wonder", "lastName": "Woman", "age": 30, "id": 2 },
            //     { "firstName": "Homer", "lastName": "Simpson", "age": 39, "id": 3 }]

            const GET_EXPECTED_BODY = [{
                "firstName": "Lisa",
                "lastName": "Simpson",
                "age": 8,
                "id": 1
            },
            {
                "firstName": "Wonder",
                "lastName": "Woman",
                "age": 30,
                "id": 2
            },
            {
                "firstName": "Homer",
                "lastName": "Simpson",
                "age": 39,
                "id": 3
            }]

            beforeEach(() => {
                const interaction = {
                    state: "i have a list of clients",
                    uponReceiving: "a request for all clients",
                    withRequest: {
                      method: "GET",
                      path: "/clients",
                      headers: {
                        Accept: "application/json, text/plain, */*",
                      },
                    },
                    willRespondWith: {
                      status: 200,
                      headers: {
                        "Content-Type": "application/json; charset=utf-8",
                      },
                      body: GET_EXPECTED_BODY,
                    },
                  }
                return mockProvider.addInteraction(interaction)  
            })

            it('will return a list of clients', async() => {

                // make request to the Pact mock server to get all clients
                const response = await getClients()
                expect(response.headers['content-type']).toBe("application/json; charset=utf-8")
                expect(response.data).toEqual(GET_EXPECTED_BODY)
                expect(response.status).toEqual(200)
            })
        })
    })

 })

Provider test code - pact.provider.spec.js

const path = require("path")
const { Verifier } = require("@pact-foundation/pact")
const { server, importData } = require("../../src/provider")
require('dotenv').config()

jest.setTimeout(30000);

describe("Clients Service Pact verification", () => {

    const port = 8081
    let opts = {
        provider: "Clients Service",
        logLevel: "DEBUG",
        providerBaseUrl: `http://localhost:${port}`,
        // pactUrls: [path.resolve(process.cwd(), "./__tests__/pacts/pact-consumer-pact-provider.json")],
        pactBrokerUrl: process.env.PACT_BROKER_BASE_URL,
        pactBrokerToken: process.env.PACT_BROKER_TOKEN,
        consumerVersionTags: ["pact-consumer"],
        providerVersionTags: ["pact-provider"],
        publishVerificationResult: false,
        providerVersion: "1.0.0"
    }

    // Start real provider server
    beforeAll(async () => {
        server.listen(port, () => {
            importData()
            console.log(`Provider listening on http://localhost:${port}`)
        })
    })

    it("validates the expectations of the clients service", () => {

        return new Verifier(opts).verifyProvider().then(output => {
            console.log("Pact Verification Complete!")
            console.log(output)
        })
    })

    afterAll(async ()=> {
        server.close();
    })
    // it('should validate the expectations of Order Web', () => {
    //     return new Verifier().verifyProvider(opts)
    //   })
})

My pact contract is here:-

{
  "consumer": {
    "name": "pact-consumer"
  },
  "provider": {
    "name": "pact-provider"
  },
  "interactions": [
    {
      "description": "a request for all clients",
      "providerState": "i have a list of clients",
      "request": {
        "method": "GET",
        "path": "/clients",
        "headers": {
          "Accept": "application/json, text/plain, */*"
        }
      },
      "response": {
        "status": 200,
        "headers": {
          "Content-Type": "application/json; charset=utf-8"
        },
        "body": [
          {
            "firstName": "Lisa",
            "lastName": "Simpson",
            "age": 8,
            "id": 1
          },
          {
            "firstName": "Wonder",
            "lastName": "Woman",
            "age": 30,
            "id": 2
          },
          {
            "firstName": "Homer",
            "lastName": "Simpson",
            "age": 39,
            "id": 3
          }
        ]
      }
    }
  ],
  "metadata": {
    "pactSpecification": {
      "version": "2.0.0"
    }
  }
}

This is my PactFlow:-

enter image description here

Verbose Error log:-

[2022-04-13 16:57:12.453 +0000] INFO (15316 on DESKTOP-TJVM91P): [email protected]: Verifying provider
  console.log
    Provider listening on http://localhost:8081

      at Server.<anonymous> (__tests__/provider/pact.provider.spec.js:28:21)

[2022-04-13 16:57:12.481 +0000] INFO (15316 on DESKTOP-TJVM91P): [email protected]: Verifying Pacts.
[2022-04-13 16:57:12.483 +0000] INFO (15316 on DESKTOP-TJVM91P): [email protected]: Verifying Pact Files
[2022-04-13 16:57:12.484 +0000] DEBUG (15316 on DESKTOP-TJVM91P): [email protected]: Starting pact binary 'D:\p\pact-nodejs-demo\node_modules\@pact-foundation\pact-node\standalone\win32-1.88.83\pact\bin\pact-provider-verifier.bat', with arguments [--provider-states-setup-url http://localhost:59761/_pactSetup --provider Clients Service --log-level DEBUG --provider-base-url http://localhost:59761 --pact-broker-base-url https://******.pactflow.io --broker-token 1iB-FQbUuvpxce6QX-DBTQ --consumer-version-tag pact-consumer --provider-version-tag pact-provider --publish-verification-results false --provider-app-version 1.0.0 --verbose true]
[2022-04-13 16:57:12.491 +0000] DEBUG (15316 on DESKTOP-TJVM91P): [email protected]: Created 'D:\p\pact-nodejs-demo\node_modules\@pact-foundation\pact-node\standalone\win32-1.88.83\pact\bin\pact-provider-verifier.bat' process with PID: 10524
FAIL __tests__/provider/pact.provider.spec.js (9.938s)
  Clients Service Pact verification
    × validates the expectations of the clients service (8022ms)

  ● Clients Service Pact verification › validates the expectations of the clients service

    D:/p/pact-nodejs-demo/node_modules/@pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-1.62.0/lib/pact/hal/entity.rb:102:in `assert_success!': Error retrieving https://******.pactflow.io/pacts/provider/Clients%20Service/for-verification status=404  (Pact::Hal::ErrorResponseReturned)
        from D:/p/pact-nodejs-demo/node_modules/@pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-1.62.0/lib/pact/hal/link.rb:65:in `post!'
        from D:/p/pact-nodejs-demo/node_modules/@pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-1.62.0/lib/pact/pact_broker/fetch_pact_uris_for_verification.rb:75:in `pacts_for_verification_entity'
        from D:/p/pact-nodejs-demo/node_modules/@pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-1.62.0/lib/pact/pact_broker/fetch_pact_uris_for_verification.rb:61:in `pacts_for_verification'
        from D:/p/pact-nodejs-demo/node_modules/@pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-1.62.0/lib/pact/pact_broker/fetch_pact_uris_for_verification.rb:44:in `call'
        from D:/p/pact-nodejs-demo/node_modules/@pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-1.62.0/lib/pact/pact_broker/fetch_pact_uris_for_verification.rb:38:in `call'

        from D:/p/pact-nodejs-demo/node_modules/@pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-1.62.0/lib/pact/pact_broker.rb:18:in `fetch_pact_uris_for_verification'
        from D:/p/pact-nodejs-demo/node_modules/@pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.36.1/lib/pact/provider_verifier/aggregate_pact_configs.rb:46:in `pacts_for_verification'
        from D:/p/pact-nodejs-demo/node_modules/@pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.36.1/lib/pact/provider_verifier/aggregate_pact_configs.rb:39:in `pacts_urls_from_broker'
        from D:/p/pact-nodejs-demo/node_modules/@pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.36.1/lib/pact/provider_verifier/aggregate_pact_configs.rb:26:in `call'
        from D:/p/pact-nodejs-demo/node_modules/@pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.36.1/lib/pact/provider_verifier/aggregate_pact_configs.rb:10:in `call'
        from D:/p/pact-nodejs-demo/node_modules/@pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.36.1/lib/pact/provider_verifier/app.rb:211:in `all_pact_urls'
        from D:/p/pact-nodejs-demo/node_modules/@pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.36.1/lib/pact/provider_verifier/app.rb:225:in `warn_empty_pact_set'
        from D:/p/pact-nodejs-demo/node_modules/@pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.36.1/lib/pact/provider_verifier/app.rb:40:in `call'
        from D:/p/pact-nodejs-demo/node_modules/@pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.36.1/lib/pact/provider_verifier/app.rb:35:in `call'
        from D:/p/pact-nodejs-demo/node_modules/@pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.36.1/lib/pact/provider_verifier/cli/verify.rb:49:in `verify'
        from D:/p/pact-nodejs-demo/node_modules/@pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/thor-1.2.1/lib/thor/command.rb:27:in 
`run'
        from D:/p/pact-nodejs-demo/node_modules/@pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/thor-1.2.1/lib/thor/invocation.rb:127:in `invoke_command'
        from D:/p/pact-nodejs-demo/node_modules/@pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/thor-1.2.1/lib/thor.rb:392:in `dispatch'
        from D:/p/pact-nodejs-demo/node_modules/@pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/thor-1.2.1/lib/thor/base.rb:485:in `start'
        from D:/p/pact-nodejs-demo/node_modules/@pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.36.1/lib/pact/provider_verifier/cli/custom_thor.rb:17:in `start'
        from D:/p/pact-nodejs-demo/node_modules/@pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/app/pact-provider-verifier.rb:33:in `<main>'

    opening connection to ******.pactflow.io:443...
    opened
    starting SSL for ******.pactflow.io:443...
    SSL established
    <- "GET / HTTP/1.1\r\nAccept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3\r\nAccept: application/hal+json\r\nUser-Agent: Ruby\r\nAuthorization: [redacted]\r\n" 
    -> "HTTP/1.1 200 OK\r\n"
    -> "Date: Wed, 13 Apr 2022 16:57:19 GMT\r\n"
    -> "Content-Type: application/hal+json;charset=utf-8\r\n"
    -> "Content-Length: 5555\r\n"
    -> "Connection: keep-alive\r\n"
    -> "Vary: Accept\r\n"
    -> "Server: Webmachine-Ruby/1.6.0 Rack/1.3\r\n"
    -> "X-Pact-Broker-Version: 2.98.0\r\n"
    -> "X-Pact-Broker-Git-Sha: 3a08d128\r\n"
    -> "X-Pactflow-Git-Sha: 85e7754e3\r\n"
    -> "X-Content-Type-Options: nosniff\r\n"
    -> "Strict-Transport-Security: max-age=63072000; includeSubDomains; preload\r\n"
    -> "X-Request-Id: cb35bba1d72c207abc7d787cbb5f4473\r\n"
    -> "\r\n"
    reading 5555 bytes...
    -> "{\"_links\":{\"self\":{\"href\":\"https://******.pactflow.io\",\"title\":\"Index\",\"templated\":false},\"pb:publish-pact\":{\"href\":\"https://******.pactflow.io/pacts/provider/{provider}/consumer/{consumer}/version/{consumerApplicationVersion}\",\"title\":\"Publish a pact\",\"templated\":true},\"pb:publish-contracts\":{\"href\":\"https://******.pactflow.io/contracts/publish\",\"title\":\"Publish contracts\",\"templated\":false},\"pb:latest-pact-versions\":{\"href\":\"https://******.pactflow.io/pacts/latest\",\"title\":\"Latest pact versions\",\"templated\":false},\"pb:tagged-pact-versions\":{\"href\":\"https://******.pactflow.io/pacts/provider/{provider}/consumer/{consumer}/tag/{tag}\",\"title\":\"All versions of a pact for a given consumer, provider and consumer version tag\",\"templated\":false},\"pb:pacticipants\":{\"href\":\"https://******.pactflow.io/pacticipants\",\"title\":\"Pacticipants\",\"templated\":false},\"pb:pacticipant\":{\"href\":\"https://******.pactflow.io/pacticipants/{pacticipant}\",\"title\":\"Fetch pacticipant by name\",\"templated\":true},\"pb:latest-provider-pacts\":{\"href\":\"https://******.pactflow.io/pacts/provider/{provider}/latest\",\"title\":\"Latest pacts by provider\",\"templated\":true},\"pb:latest-provider-pacts-with-tag\":{\"href\":\"https://******.pactflow.io/pacts/provider/{provider}/latest/{tag}\",\"title\":\"Latest pacts for provider with the specified tag\",\"templated\":true},\"pb:provider-pacts-with-tag\":{\"href\":\"https://******.pactflow.io/pacts/provider/{provider}/tag/{tag}\",\"title\":\"All pact versions for the provider with the specified consumer version tag\",\"templated\":true},\"pb:provider-pacts\":{\"href\":\"https://******.pactflow.io/pacts/provider/{provider}\",\"title\":\"All pact versions for the specified provider\",\"templated\":true},\"pb:latest-version\":{\"href\":\"https://******.pactflow.io/pacticipants/{pacticipant}/latest-version\",\"title\":\"Latest pacticipant version\",\"templated\":true},\"pb:latest-tagged-version\":{\"href\":\"https://******.pactflow.io/pacticipants/{pacticipant}/latest-version/{tag}\",\"title\":\"Latest pacticipant version with the specified tag\",\"templated\":true},\"pb:webhooks\":{\"href\":\"https://******.pactflow.io/webhooks\",\"title\":\"Webhooks\",\"templated\":false},\"pb:webhook\":{\"href\":\"https://******.pactflow.io/webhooks/{uuid}\",\"title\":\"Webhook\",\"templated\":true},\"pb:integrations\":{\"href\":\"https://******.pactflow.io/integrations\",\"title\":\"Integrations\",\"templated\":false},\"pb:pacticipant-version-tag\":{\"href\":\"https://******.pactflow.io/pacticipants/{pacticipant}/versions/{version}/tags/{tag}\",\"title\":\"Get, create or delete a tag for a pacticipant version\",\"templated\":true},\"pb:pacticipant-branch-version\":{\"href\":\"https://******.pactflow.io/pacticipants/{pacticipant}/branches/{branch}/versions/{version}\",\"title\":\"Get or add/create a pacticipant version for a branch\",\"templated\":true},\"pb:pacticipant-version\":{\"href\":\"https://******.pactflow.io/pacticipants/{pacticipant}/versions/{version}\",\"title\":\"Get, create or delete a pacticipant version\",\"templated\":true},\"pb:metrics\":{\"href\":\"https://******.pactflow.io/metrics\",\"title\":\"Get Pact Broker metrics\"},\"pb:can-i-deploy-pacticipant-version-to-tag\":{\"href\":\"https://******.pactflow.io/can-i-deploy?pacticipant={pacticipant}\\u0026version={version}\\u0026to={tag}\",\"title\":\"Determine if an application version can be safely deployed to an environment identified by the given tag\",\"templated\":true},\"pb:can-i-deploy-pacticipant-version-to-environment\":{\"href\":\"https://******.pactflow.io/can-i-deploy?pacticipant={pacticipant}\\u0026version={version}\\u0026environment={environment}\",\"title\":\"Determine if an application version can be safely deployed to an environment\",\"templated\":true},\"pb:provider-pacts-for-verification\":{\"href\":\"https://******.pactflow.io/pacts/provider/{provider}/for-verification\",\"title\":\"Pact versions to be verified for the specified provider\",\"templated\":true},\"beta:provider-pacts-for-verification\":{\"name\":\"beta\",\"href\":\"https://******.pactflow.io/pacts/provider/{provider}/for-verification\",\"title\":\"DEPRECATED - please use pb:provider-pacts-for-verification\",\"templated\":true},\"curies\":[{\"name\":\"pb\",\"href\":\"https://******.pactflow.io/doc/{rel}?context=index\",\"templated\":true},{\"name\":\"beta\",\"href\":\"https://******.pactflow.io/doc/{rel}?context=index\",\"templated\":true}],\"pb:environments\":{\"title\":\"Environments\",\"href\":\"https://******.pactflow.io/environments\",\"templated\":false},\"pb:environment\":{\"title\":\"Environment\",\"href\":\"https://******.pactflow.io/environments/{uuid}\",\"templated\":true},\"pb:api-tokens\":{\"href\":\"https://******.pactflow.io/settings/tokens\",\"title\":\"API tokens\",\"templated\":false},\"pb:audit\":{\"href\":\"https://******.pactflow.io/audit\",\"title\":\"Audit trail\",\"templated\":false},\"pb:secrets\":{\"href\":\"https://******.pactflow.io/secrets\",\"title\":\"Secrets\",\"templated\":false},\"pf:admin-users\":{\"href\":\"https://******.pactflow.io/admin/users\",\"title\":\"Users\",\"templated\":false},\"pf:admin-teams\":{\"href\":\"https://******.pactflow.io/admin/teams\",\"title\":\"Teams\",\"templated\":false},\"pf:admin-system-accounts\":{\"href\":\"https://******.pactflow.io/admin/system-accounts\",\"title\":\"System accounts\",\"templated\":false},\"pf:admin-roles\":{\"href\":\"https://******.pactflow.io/admin/roles\",\"title\":\"Roles\",\"templated\":false},\"pf:admin-permissions\":{\"href\":\"https://******.pactflow.io/admin/permissions\",\"title\":\"Permissions\",\"templated\":false},\"pf:admin-authentication-settings\":{\"href\":\"https://******.pactflow.io/admin/tenant/authentication-settings\",\"title\":\"Authentication Settings\",\"templated\":false},\"pf:user-allocations\":{\"href\":\"https://******.pactflow.io/tenant/limits\",\"title\":\"User Allocations\",\"templated\":false}}}"

Upvotes: 0

Views: 3250

Answers (1)

Matthew Fellows
Matthew Fellows

Reputation: 4065

It's quite simple. You have defined the provider in you consumer test (and what's in the contract) as pact-provider.

In your provider test, however, it is called Clients Service.

When your provider test is trying to discover the contracts, it uses the provider name as the key. Because there is no provider called Clients Service it's getting a a 404.

Either

  1. Update the provider name in the consumer to to Clients Service (and delete the old integration)
  2. Update the provider name to pact-provider

(1. seems like the right thing to do)

Upvotes: 1

Related Questions