【问题标题】:How to use SinonJs to spy on number of async calls without await如何使用 SinonJs 监视异步调用的数量而无需等待
【发布时间】:2021-05-09 10:59:03
【问题描述】:

在下面的示例中,我有两个函数 doTask 和 doSubTask。两者都是异步的,但是由于某些业务需要,我需要使用不同的参数触发并忘记 doSubTask 两次

const wait = ms => new Promise(resolve => setTimeout(resolve, ms))

const doTask = async (taskId) => {
  await wait(taskId)
  doSubTask(taskId * 3)
  doSubTask(taskId * 5)
  console.log('end task :' + taskId)
}

const doSubTask = async (subTaskId) => {
  await wait(subTaskId)
  console.log('end subTask :' + subTaskId)
}

doTask(2000)

如何为 doTask 编写测试用例,并断言 doSubTask 已被调用两次?


这是一个代码示例,你可以在runkit.com上运行它

require("@fatso83/mini-mocha").install()

const sinon = require("sinon@7.5.0")
const referee = require("@sinonjs/referee")
const chai = require('chai')
chai.use(require('sinon-chai'))
const expect = chai.expect

const wait = ms => new Promise(resolve => setTimeout(resolve, ms))

const doTask = async (taskId) => {
  await wait(taskId)
  doSubTask(taskId * 3)
  doSubTask(taskId * 5)
  console.log('end task :' + taskId)
}

const doSubTask = async (subTaskId) => {
  await wait(subTaskId)
  console.log('end subTask :' + subTaskId)
}

const app = {
  doTask,
  doSubTask,
}

describe("stub", function () {
  it("doSubTask should be called twice", async function () {
    const doSubTaskSpy = sinon.spy(app, 'doSubTask')
    
    await doTask(2000)
    
    expect(doSubTaskSpy).to.be.calledTwice()
  })
})

上述代码的输出是:

stub
end task :2000
❌ doSubTask should be called twice (Failed with: "expecte…e been called exactly twice, but it was called 0 times")
end subTask :6000
end subTask :10000

【问题讨论】:

    标签: javascript async-await mocha.js chai sinon


    【解决方案1】:

    我们应该使用rewire 包来要求模块和存根doSubTask 函数。此外,我们应该使用this way来使用假计时器,并在您同时使用promisesetTimeout时将时间提前。

    例如

    index.js:

    const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
    
    const doTask = async (taskId) => {
      await wait(taskId);
      doSubTask(taskId * 3);
      doSubTask(taskId * 5);
      console.log('end task :' + taskId);
    };
    
    const doSubTask = async (subTaskId) => {
      await wait(subTaskId);
      console.log('end subTask :' + subTaskId);
    };
    
    const app = {
      doTask,
      doSubTask,
    };
    
    module.exports = app;
    

    index.test.js:

    const rewire = require('rewire');
    const sinon = require('sinon');
    
    describe('stub', function () {
      let clock;
      before(() => {
        clock = sinon.useFakeTimers();
      });
      after(() => {
        clock.restore();
      });
      it('doSubTask should be called twice', async function () {
        const doSubTaskStub = sinon.stub();
        const mod = rewire('./');
        mod.__set__('doSubTask', doSubTaskStub);
        const promise = mod.doTask(2000);
        clock.tick(2010);
        await promise;
        sinon.assert.calledTwice(doSubTaskStub);
        sinon.assert.calledWithExactly(doSubTaskStub, 6000);
        sinon.assert.calledWithExactly(doSubTaskStub, 10000);
      });
    });
    

    测试结果:

      stub
    end task :2000
        ✓ doSubTask should be called twice (738ms)
    
    
      1 passing (743ms)
    
    ----------|---------|----------|---------|---------|-------------------
    File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    ----------|---------|----------|---------|---------|-------------------
    All files |   84.62 |      100 |      75 |   81.82 |                   
     index.js |   84.62 |      100 |      75 |   81.82 | 11-12             
    ----------|---------|----------|---------|---------|-------------------
    

    【讨论】:

      猜你喜欢
      • 2019-01-08
      • 2012-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多