PACT.io:在运行npm时运行pactTest

时间:2018-09-26 15:02:21

标签: javascript typescript testing pact

测试仓库已创建:https://github.com/leongaban/pact-io-js-test

enter image description here

预期

运行npm run pactTest,这将为我的TotalPayout.test.pact.ts文件创建一个Pact文件。

结果

D, [#38238] DEBUG -- : {
  "description": "a GET request with a user id",
  "request": {
    "method": "GET",
    "path": "/frontoffice/api/liquidity-pool/get-total-payout",
    "headers": {
      "Accept": "application/json"
    }
  },
  "response": {
    "status": 200,
    "headers": {
      "Content-Type": "application/json"
    }
  }
}
W, [#38238]  WARN -- : Verifying - actual interactions do not match expected interactions. 
Missing requests:
  GET /frontoffice/api/liquidity-pool/get-total-payout


W, [#38238]  WARN -- : Missing requests:
  GET /frontoffice/api/liquidity-pool/get-total-payout

这是我的契约文件

// @ts-ignore
import path from 'path';
// @ts-ignore
import { Pact } from '@pact-foundation/pact';
import { getTotalPayout } from './LiquidityPool';

// const port = 12345;
const endpoint = '/frontoffice/api/liquidity-pool/get-total-payout';

const EXPECTED_BODY = {
  total_payout: 100.21,
};

const userId = 'foo';

describe('The API', () => {
  // Copy this block once per interaction under test
  describe('getUsersTotalPayout', () => {
    beforeEach(() => {
      const interaction = {
        uponReceiving: 'a GET request with a user id',
        withRequest: {
          method: 'GET',
          path: endpoint,
          headers: {
            Accept: 'application/json',
          },
        },
        willRespondWith: {
          status: 200,
          headers: {
            'Content-Type': 'application/json'
          },
          data: EXPECTED_BODY
        },
      };

      // @ts-ignore
      return provider.addInteraction(interaction);
    });
​
    // add expectations
    it('Should call getUsersTotalPayout and return an object with the total_payout', done => {
      getTotalPayout(userId)
        .then((response: any) => {
          console.log('response', response);
          console.log('EXPECTED_BODY', EXPECTED_BODY);
          expect(response).toEqual(EXPECTED_BODY);
        })
        .then(done);
    });
  });
});

这是包含 getTotalPayout 功能的服务文件:

该端点尚不存在,但据我理解,该Pact测试应该仍然有效。

// @TODO Note, this is the placeholder for LiquidityPool API endpoints
// @ts-ignore
import axios, * as others from 'axios';

const endpoint = '/frontoffice/api/liquidity-pool/';

export const getTotalPayout = async (userId: string) => {
  const response = await axios.get(`${endpoint}get-total-payout`, { params: userId });
  return response.data;
};

也是我的 axios 模拟 src/__mocks__/axios.ts

// tslint:disable-next-line:no-empty
const mockNoop = () => new Promise(() => {});

export default {
  get: jest.fn(() => Promise.resolve({ data: { total_payout: 100.21 }})),
  default: mockNoop,
  post: mockNoop,
  put: mockNoop,
  delete: mockNoop,
  patch: mockNoop
};

1 个答案:

答案 0 :(得分:2)

非常简单-您的测试不是在Pact Mock服务器上击中路径/frontoffice/api/liquidity-pool/get-total-payout

您已将Pact设置为在http://localhost:1234上运行,因此需要将实际代码配置为在该服务器上运行,而不是真正的服务器。

在axios配置中,您正在模拟http请求库,因此它什么也不做。因此,当您的实际代码使用它时,它不会发出http调用,并且Pact测试也会失败,因为它希望以某种形状调用并且没有得到它。

这是您需要更改的内容:

  1. Axios似乎已被使用,但不在您的package.json中。我猜是因为您在嘲笑(2)。您需要一个实际的http请求库,因此您可能应该只安装axios
  2. Axios被模拟以提供固定的响应,请勿在Pact测试期间模拟axios(如果需要,对于本地开发人员也可以),因为这将阻止对Pact的真实调用。 Pact需要真正的http调用,以便它可以检查您的代码在做正确的事情,然后将找到的内容写到“合同”中
  3. 在测试中配置axios以打通Pact模拟服务。假设您使用axios,应该执行以下操作:

pactSetup.ts:

  // Configure axios to use the Pact mock server for Pact tests
  import axios from "axios";
  axios.defaults.baseURL = "http://localhost:1234";
  1. 读取Pact吐出的日志文件。它告诉您发生了什么。再重申一次:您已告知Pact,/frontoffice/api/liquidity-pool/get-total-payout上应该有一个互动,但从未收到。使您的实际代码达到此水平,然后您会没事的。

最后,顺便说一句,一旦开始生成Pact(固定1-4之后),您可能希望将Pact用作本地开发的本地存根服务器。该二进制文件实际上已经安装在您的node_modules中,其运行方式的文档位于https://github.com/pact-foundation/pact-ruby-standalone/releases

我通常在package.json中有一个脚本,如下所示:

  "stubs": "$(find . -name pact-stub-service | head -n 1) pacts/* --port 4000"

然后您可以运行npm run stubs,并在端口4000上运行提供程序的本地存根,并将所有请求/响应放入测试中。