單位測試承諾與 Mocha Sinon Chai 和 Proxyquire

在這裡,我們有一個簡單的測試類,它根據外部 ResponseProcessor 的結果返回一個 Promise,這需要時間來執行。

為了簡單起見,我們假設 processResponse 方法永遠不會失敗。

import {processResponse} from '../utils/response_processor';

const ping = () => {
  return new Promise((resolve, _reject) => {
    const response = processResponse(data);
    resolve(response);
  });
}

module.exports = ping;

為了測試這一點,我們可以利用以下工具。

  1. mocha
  2. chai
  3. sinon
  4. proxyquire
  5. chai-as-promised

我在 package.json 檔案中使用了以下 test 指令碼。

"test": "NODE_ENV=test mocha --compilers js:babel-core/register --require ./test/unit/test_helper.js  --recursive test/**/*_spec.js"

這允許我使用 es6 語法。它引用了一個看起來像的 test_helper

import chai from 'chai';
import sinon from 'sinon';
import sinonChai from 'sinon-chai';
import chaiAsPromised from 'chai-as-promised';
import sinonStubPromise from 'sinon-stub-promise';

chai.use(sinonChai);
chai.use(chaiAsPromised);
sinonStubPromise(sinon);

Proxyquire 允許我們在外部 ResponseProcessor 的位置注入我們自己的存根。然後我們可以使用 sinon 監視存根的方法。我們使用了 chai 的擴充套件,chai-as-promised 注入以檢查 ping() 方法的承諾是 fullfilled,並且 eventually 返回所需的響應。

import {expect}       from 'chai';
import sinon          from 'sinon';
import proxyquire     from 'proxyquire';

let formattingStub = {
  wrapResponse: () => {}
}

let ping = proxyquire('../../../src/api/ping', {
  '../utils/formatting': formattingStub
});

describe('ping', () => {
  let wrapResponseSpy, pingResult;
  const response = 'some response';

  beforeEach(() => {
    wrapResponseSpy = sinon.stub(formattingStub, 'wrapResponse').returns(response);
    pingResult = ping();
  })

  afterEach(() => {
    formattingStub.wrapResponse.restore();
  })

  it('returns a fullfilled promise', () => {
    expect(pingResult).to.be.fulfilled;
  })

  it('eventually returns the correct response', () => {
    expect(pingResult).to.eventually.equal(response);
  })
});

現在讓我們假設你希望測試使用 ping 響應的內容。

import {ping} from './ping';

const pingWrapper = () => {
  ping.then((response) => {
    // do something with the response
  });
}

module.exports = pingWrapper;

為了測試 pingWrapper 我們利用

  1. sinon
  2. proxyquire
  3. sinon-stub-promise

和以前一樣,Proxyquire 允許我們在外部依賴的位置注入我們自己的存根,在這種情況下我們之前測試過的 ping 方法。然後我們可以使用 sinon 監視那個存根的方法,並利用 sinon-stub-promise 來允許我們使用。然後可以在測試中解析或拒絕此承諾,以便測試包裝器對此的響應。

import {expect}   from 'chai';
import sinon      from 'sinon';
import proxyquire from 'proxyquire';

let pingStub = {
  ping: () => {}
};

let pingWrapper = proxyquire('../src/pingWrapper', {
  './ping': pingStub
});

describe('pingWrapper', () => {
  let pingSpy;
  const response = 'some response';

  beforeEach(() => {
    pingSpy = sinon.stub(pingStub, 'ping').returnsPromise();
    pingSpy.resolves(response);
    pingWrapper();
  });

  afterEach(() => {
    pingStub.wrapResponse.restore();
  });

  it('wraps the ping', () => {
    expect(pingSpy).to.have.been.calledWith(response);
  });
});