It means your API client code being tested, is not...
# pact-js
m
It means your API client code being tested, is not sending the request to the mock service configured by Pact. Pact does not automatically mock your API calls - you need to ensure your API client is correctly configured to poitn at the Pact mock service. Given you have constructed a Pact object with name
provider
and you are using a
DogApiClient
class to send requests to your
Dog Service
, you can dynamically configure your API client as follows:
Copy code
provider.setup().then(opts => {
  dogService = new DogApiClient({ `http://${opts.host}`, port: opts.port })
})
b
Hello Matt. Thanks for quick response. My spec file is here:
Copy code
/* eslint-disable no-undef */
/* eslint-disable no-console */
jest.unmock("axios");
import axios from "axios";
import MockAdapter from "axios-mock-adapter";
import { Pact, Matchers } from "@pact-foundation/pact";
import { API } from "./api";
const path = require("path");
const { string, boolean } = Matchers;

jest.setTimeout(30000);

let mockService;
const mock = new MockAdapter(axios);

const expectedResponse = {
  status: true,
  message: "İşlem başarılı.",
};

const pactProvider = new Pact({
  port: 3001,
  consumer: "mcontent-consumer",
  provider: "mcontent-provider",
  logLevel: "debug",
  spec: 2,
  cors: true,
});

beforeAll(() => pactProvider.setup().then(() => {
  mockService = new API(pactProvider.mockService.baseUrl)
}));
afterAll(() => pactProvider.finalize());

describe("Pact Contract Testing", () => {
  describe("retrieving a merchant by id", () => {
    test("Test deneme", async () => {
      try {
        await pactProvider.addInteraction({
          state: "a merchant with Merchant ID exists",
          uponReceiving: "a request to get a merchant",
          withRequest: {
            method: "GET",
            path: pactProvider.mockService.baseUrl + "/merchants",
          },
          willRespondWith: {
            status: 404,
            body: {
              status: boolean(true),
              message: string("İşlem başarılı."),
            },
          },
        });
        mock.onGet("<http://127.0.0.1:3001/merchants>").reply(200, expectedResponse, { headers: {} });
        const response = await mockService.getMerchantById();

        // Assert - did we get the expected response
        expect(response).toStrictEqual(expectedResponse);
        await pactProvider.verify();
      } catch (error) {
        console.log("error", error);
      }
    });

    // afterEach(() => pactProvider.verify().then((err) => console.log(err).catch((err) => console.log(err))));
  });
});
Also, you find the API page below:
Copy code
import axios from "axios";

export class API {
  constructor(url) {
    this.url = url;
  }

  async getMerchantById() {
    console.log("this.url", this.url);
    return axios.get(this.url + "/merchants").then((data) => data.data);
  }
}

export default API;
I got this error:
Copy code
[2022-05-18 12:31:18.699 +0000] INFO (78491 on THB-ARG-437.local): pact-node@10.17.2: Creating Pact Server with options: 
{"timeout":30000,"consumer":"mcontent-consumer","cors":true,"dir":"/Users/bsafranbolulu/Desktop/Projects/MerchantContent/mc-frontend/pacts","host":"127.0.0.1","log":"/Users/bsafranbolulu/Desktop/Projects/MerchantContent/mc-frontend/logs/pact.log","logLevel":"DEBUG","pactfileWriteMode":"overwrite","provider":"mcontent-provider","spec":2,"ssl":false,"port":3001,"pactFileWriteMode":"overwrite"}
[2022-05-18 12:31:18.712 +0000] DEBUG (78491 on THB-ARG-437.local): pact-node@10.17.2: Starting pact binary '/Users/bsafranbolulu/Desktop/Projects/MerchantContent/mc-frontend/node_modules/@pact-foundation/pact-node/standalone/darwin-1.88.83/pact/bin/pact-mock-service', with arguments [service --consumer mcontent-consumer --cors true --pact_dir /Users/bsafranbolulu/Desktop/Projects/MerchantContent/mc-frontend/pacts --host 127.0.0.1 --log /Users/bsafranbolulu/Desktop/Projects/MerchantContent/mc-frontend/logs/pact.log --log-level DEBUG --provider mcontent-provider --pact_specification_version 2 --ssl false --port 3001 --pact-file-write-mode overwrite]
[2022-05-18 12:31:18.718 +0000] DEBUG (78491 on THB-ARG-437.local): pact-node@10.17.2: Created '/Users/bsafranbolulu/Desktop/Projects/MerchantContent/mc-frontend/node_modules/@pact-foundation/pact-node/standalone/darwin-1.88.83/pact/bin/pact-mock-service' process with PID: 78509
[2022-05-18 12:31:19.491 +0000] DEBUG (78491 on THB-ARG-437.local): pact-node@10.17.2: INFO  WEBrick 1.3.1
INFO  ruby 2.2.2 (2015-04-13) [x86_64-darwin13]

[2022-05-18 12:31:19.492 +0000] DEBUG (78491 on THB-ARG-437.local): pact-node@10.17.2: INFO  WEBrick::HTTPServer#start: pid=78509 port=3001

[2022-05-18 12:31:19.748 +0000] INFO (78491 on THB-ARG-437.local): pact@9.17.3: Setting up Pact with Consumer "mcontent-consumer" and Provider "mcontent-provider"
    using mock service on Port: "3001"
  console.log
    this.url <http://127.0.0.1:3001>

      at API._callee$ (src/universal/partials/AboutSeller/pact_test/api.js:9:13)

  console.error
    

      at node_modules/@pact-foundation/src/httpPact.ts:151:17

  console.error
    Pact verification failed!

      at node_modules/@pact-foundation/src/httpPact.ts:152:17

  console.error
    Actual interactions do not match expected interactions for mock MockService.
    
    Missing requests:
        GET <http://127.0.0.1:3001/merchants>
    
    
    See /Users/bsafranbolulu/Desktop/Projects/MerchantContent/mc-frontend/logs/pact.log for details.
    

      at node_modules/@pact-foundation/src/httpPact.ts:153:17

  console.log
    error Error: Pact verification failed - expected interactions did not match actual.
        at new VerificationError (/Users/bsafranbolulu/Desktop/Projects/MerchantContent/mc-frontend/node_modules/@pact-foundation/pact/src/errors/verificationError.js:19:42)
        at /Users/bsafranbolulu/Desktop/Projects/MerchantContent/mc-frontend/node_modules/@pact-foundation/src/httpPact.ts:157:17
        at processTicksAndRejections (internal/process/task_queues.js:95:5)

      at _callee$ (src/universal/partials/AboutSeller/pact_test/aboutSeller.spec.js:61:17)
Although I have tried too many things, I couldn’t pass this “Verification failed!” issue.
Do I need to write Pact VerifiedProvider standalone javascript code?
Still got
Missing requests
issue @Matt (pactflow.io / pact-js / pact-go)
How to solve this problem?
m
I’m 99% sure you aren’t sending the requests to the mock service. Can you please share your code and the pact.log file so we can see? There are debugging instructions in the Pact JS readme that you can follow
b
I have sent all the files on DM.
@Matt (pactflow.io / pact-js / pact-go)
m
For others coming here, Berk is using nock which is going to interfere and mock network requests. You don’t want to do that, as you need to be able to send the requests to the pact mock service
b
I have to use
jest.unmock("axios")
on the top of page. How to change this code according to
Pact
?
m
I’m not sure what you’re asking, sorry
basically, don’t mock your API client code - we are testing the API client and it needs to send requests to the pact mock server
b
Copy code
I, [2022-05-19T14:17:51.552228 #94845]  INFO -- : Registered expected interaction GET /product/10
D, [2022-05-19T14:17:51.552399 #94845] DEBUG -- : {
  "description": "get product with ID 10",
  "providerState": "product with ID 10 exists",
  "request": {
    "method": "GET",
    "path": "/product/10",
    "headers": {
      "Accept": "application/json"
    }
  },
  "response": {
    "status": 200,
    "headers": {
      "Content-Type": "application/json"
    },
    "body": {
    }
  },
  "metadata": null
}
W, [2022-05-19T14:17:51.574747 #94845]  WARN -- : Verifying - actual interactions do not match expected interactions. 
Missing requests:
	GET /product/10



W, [2022-05-19T14:17:51.574788 #94845]  WARN -- : Missing requests:
	GET /product/10



I, [2022-05-19T14:17:51.587009 #94845]  INFO -- : Cleared interactions
here is the log file.
the latest version of the pact.spec.js file:
Copy code
import path from "path";
import { Pact, Matchers } from "@pact-foundation/pact";
import API from "./api";
const { like } = Matchers;

const provider = new Pact({
  consumer: "FrontendWebsite",
  provider: "ProductService",
  log: path.resolve(process.cwd(), "logs", "pact.log"),
  logLevel: "debug",
  dir: path.resolve(process.cwd(), "pacts"),
  spec: 2,
});

describe("API Pact test", () => {
  beforeAll(() => provider.setup());
  afterEach(() => provider.verify());
  afterAll(() => provider.finalize());

  describe("getting one product", () => {
    it("ID 10 exists", async () => {
      // "it" requires not "test"
      // set up Pact interactions
      await provider.addInteraction({
        state: "product with ID 10 exists",
        uponReceiving: "get product with ID 10",
        withRequest: {
          method: "GET",
          path: "/product/10",
          headers: {
            Accept: "application/json",
          },
        },
        willRespondWith: {
          status: 200,
          headers: {
            "Content-Type": "application/json",
          },
          body: {},
        },
      });

      const newApi = new API(provider.mockService.baseUrl);

      // make request to Pact mock server
      const response = await newApi.getProduct("10");

      expect(response).toEqual({});
    });
  });
});
@Matt (pactflow.io / pact-js / pact-go), Do I need to run my backend server in the background?
m
no, the pact mock server stands in for that
what does the
pact.log
file say?
also, what is the contents of
api.js
?
Ideally, if you can share a GH repo we can download to test, that will speed this up
b
pact.log
Copy code
I, [2022-05-19T14:22:18.662359 #95104]  INFO -- : Registered expected interaction GET /product/10
D, [2022-05-19T14:22:18.662506 #95104] DEBUG -- : {
  "description": "get product with ID 10",
  "providerState": "product with ID 10 exists",
  "request": {
    "method": "GET",
    "path": "/product/10",
    "headers": {
      "Accept": "application/json"
    }
  },
  "response": {
    "status": 200,
    "headers": {
      "Content-Type": "application/json"
    },
    "body": {
    }
  },
  "metadata": null
}
W, [2022-05-19T14:22:18.682967 #95104]  WARN -- : Verifying - actual interactions do not match expected interactions. 
Missing requests:
	GET /product/10



W, [2022-05-19T14:22:18.683009 #95104]  WARN -- : Missing requests:
	GET /product/10



I, [2022-05-19T14:22:18.694772 #95104]  INFO -- : Cleared interactions
api.js
Copy code
import axios from "axios";

export class API {
  constructor(url) {
    if (url === undefined || url === "") {
      url = "<http://localhost:3001>";
    }
    this.url = url;
    console.log('this.url', this.url)
  }

  async getProduct(id) {
    return axios.get(this.url + "/products/" + id).then((r) => r.data);
  }
}

export default API;
m
hmm, that
getProduct
method sends requests to
/products
not
/product
b
Same error 😕
Copy code
I, [2022-05-19T14:25:28.546777 #95323]  INFO -- : Registered expected interaction GET /products/10
D, [2022-05-19T14:25:28.546928 #95323] DEBUG -- : {
  "description": "get product with ID 10",
  "providerState": "product with ID 10 exists",
  "request": {
    "method": "GET",
    "path": "/products/10",
    "headers": {
      "Accept": "application/json"
    }
  },
  "response": {
    "status": 200,
    "headers": {
      "Content-Type": "application/json"
    },
    "body": {
    }
  },
  "metadata": null
}
W, [2022-05-19T14:25:28.569317 #95323]  WARN -- : Verifying - actual interactions do not match expected interactions. 
Missing requests:
	GET /products/10



W, [2022-05-19T14:25:28.569359 #95323]  WARN -- : Missing requests:
	GET /products/10



I, [2022-05-19T14:25:28.581871 #95323]  INFO -- : Cleared interactions
m
I’m not 100% sure why, but I noticed above that your http client seemed to want to send requests to
3001
still - can you confirm / print out the URL that
API
thinks it’s sending requests to?
b
Sure, here is the console output to detect the URL:
Copy code
[2022-05-19 11:32:29.785 +0000] INFO (95814 on THB-ARG-437.home): pact-node@10.17.2: Creating Pact Server with options: 
{"timeout":30000,"consumer":"FrontendWebsite","cors":false,"dir":"/Users/bsafranbolulu/Desktop/Projects/MerchantContent/mc-frontend/pacts","host":"127.0.0.1","log":"/Users/bsafranbolulu/Desktop/Projects/MerchantContent/mc-frontend/logs/pact.log","logLevel":"DEBUG","pactfileWriteMode":"overwrite","provider":"ProductService","spec":2,"ssl":false,"pactFileWriteMode":"overwrite"}
[2022-05-19 11:32:29.795 +0000] DEBUG (95814 on THB-ARG-437.home): pact-node@10.17.2: Starting pact binary '/Users/bsafranbolulu/Desktop/Projects/MerchantContent/mc-frontend/node_modules/@pact-foundation/pact-node/standalone/darwin-1.88.83/pact/bin/pact-mock-service', with arguments [service --consumer FrontendWebsite --cors false --pact_dir /Users/bsafranbolulu/Desktop/Projects/MerchantContent/mc-frontend/pacts --host 127.0.0.1 --log /Users/bsafranbolulu/Desktop/Projects/MerchantContent/mc-frontend/logs/pact.log --log-level DEBUG --provider ProductService --pact_specification_version 2 --ssl false --pact-file-write-mode overwrite]
[2022-05-19 11:32:29.801 +0000] DEBUG (95814 on THB-ARG-437.home): pact-node@10.17.2: Created '/Users/bsafranbolulu/Desktop/Projects/MerchantContent/mc-frontend/node_modules/@pact-foundation/pact-node/standalone/darwin-1.88.83/pact/bin/pact-mock-service' process with PID: 95823
[2022-05-19 11:32:30.314 +0000] DEBUG (95814 on THB-ARG-437.home): pact-node@10.17.2: INFO  WEBrick 1.3.1
INFO  ruby 2.2.2 (2015-04-13) [x86_64-darwin13]

[2022-05-19 11:32:30.315 +0000] DEBUG (95814 on THB-ARG-437.home): pact-node@10.17.2: INFO  WEBrick::HTTPServer#start: pid=95823 port=64311

[2022-05-19 11:32:30.315 +0000] INFO (95814 on THB-ARG-437.home): pact-node@10.17.2: Pact running on port 64311
 FAIL  test_pact/api.pact.spec.js
  API Pact test
    getting one product
      ✕ ID 10 exists (43 ms)

  ● API Pact test › getting one product › ID 10 exists

    Pact verification failed - expected interactions did not match actual.

      at new VerificationError (node_modules/@pact-foundation/pact/src/errors/verificationError.js:19:42)
      at node_modules/@pact-foundation/src/httpPact.ts:157:17

Test Suites: 1 failed, 1 passed, 2 total
Tests:       1 failed, 1 passed, 2 total
Snapshots:   0 total
Time:        3.17 s
Ran all test suites matching /\/test_pact/i.

Watch Usage: Press w to show more.[2022-05-19 11:32:30.831 +0000] INFO (95814 on THB-ARG-437.home): pact@9.17.3: Setting up Pact with Consumer "FrontendWebsite" and Provider "ProductService"
    using mock service on Port: "64311"
  console.log
    this.url <http://127.0.0.1:64311>

      at new API (test_pact/api.js:9:13)

  console.error
    

      at node_modules/@pact-foundation/src/httpPact.ts:151:17

  console.error
    Pact verification failed!

      at node_modules/@pact-foundation/src/httpPact.ts:152:17

  console.error
    Actual interactions do not match expected interactions for mock MockService.
    
    Missing requests:
        GET /products/10
    
    
    See /Users/bsafranbolulu/Desktop/Projects/MerchantContent/mc-frontend/logs/pact.log for details.
    

      at node_modules/@pact-foundation/src/httpPact.ts:153:17

[2022-05-19 11:32:30.879 +0000] INFO (95814 on THB-ARG-437.home): pact@9.17.3: Pact File Written
[2022-05-19 11:32:30.880 +0000] INFO (95814 on THB-ARG-437.home): pact-node@10.17.2: Removing Pact process with PID: 95823
[2022-05-19 11:32:30.881 +0000] DEBUG (95814 on THB-ARG-437.home): pact-node@10.17.2: INFO  going to shutdown ...
INFO  WEBrick::HTTPServer#start done.

[2022-05-19 11:32:30.882 +0000] INFO (95814 on THB-ARG-437.home): pact-node@10.17.2: Deleting Pact Server with options: 
{"timeout":30000,"consumer":"FrontendWebsite","cors":false,"dir":"/Users/bsafranbolulu/Desktop/Projects/MerchantContent/mc-frontend/pacts","host":"127.0.0.1","log":"/Users/bsafranbolulu/Desktop/Projects/MerchantContent/mc-frontend/logs/pact.log","logLevel":"DEBUG","pactfileWriteMode":"overwrite","provider":"ProductService","spec":2,"ssl":false,"port":64311,"pactFileWriteMode":"overwrite"}
I think that the URL is correct.
Copy code
using mock service on Port: "64311"
  console.log
    this.url <http://127.0.0.1:64311>
m
yep, that does look correct
Is there anything else in the code base that could be interfering? If you could please create an example pact project I can clone and test locally, I think that’s the next course of action. This code looks OK to me, so I think I’ve exhausted the options through words 😛
b
This project is a kind of microfrontend project that we built from scratch. It’s based on Nodejs but we are able to write React codes here. But, I think that I should use the node package for Pact. What do you think about that?
m
that’s correct, you still use the node package because it should work for your testing frameworks like jest etc.
b
So It means you suggest to use
@pact-foundation/node
right?
m
I don’t think that’s a package
@pact-foundation/pact
b
I got it. I can’t share the project due to being private for the company.
Do you have any method for detecting the issue with all the details?
m
if I could do that, I’d be a billionaire!
b
hahaha 😄
m
So, we know the example project works. All I can reason at this point is that there is some other dependency/code/xyz that is interfering here
is there a jest config that is auto-mocking everything?
b
I had a jest config but I have already deleted it.
m
so, delete everything until you have the working example project, and then one by one add it back
b
I’m agree with you, For example:
Copy code
jest.unmock("axios")
import API from "./api";
import nock from "nock";

describe("API", () => {
  test("get product ID 50", async () => {
    const product = {
      id: "50",
      type: "CREDIT_CARD",
      name: "28 Degrees",
      version: "v1",
    };

    const url = "<http://localhost:3001>"
    const api = new API(url)
    nock(api.url).get("/products/50").reply(200, product, { "Access-Control-Allow-Origin": "*" });
    const respProduct = await api.getProduct("50");
    expect(respProduct).toEqual(product);
  });
});
Tests are not working without the code I added on the top.
It means jest automatically mocks everything.
We need to pass a parameter
axios
when we’re using
jest.unmock()
method. That’s why I asked before, what should I write as a parameter on
jest.unmock()
method If I want to use it for
pact?
m
We need to pass a parameter
axios
when we’re using
jest.unmock()
method. That’s why I asked before, what should I write as a parameter on
jest.unmock()
method If I want to use it for
pact?
well, it depends on what it mocks. I don’t know what tools you’re using so I can’t say (I know a bit more now, of course)