单位测试承诺与 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);
  });
});