使用Mocha和sinon测试异步功能 [英] Test async function with mocha and sinon

查看:152
本文介绍了使用Mocha和sinon测试异步功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我做了一个小功能,可以通过套接字发出消息,我正在尝试使用mocha和sinon对其进行测试:

I am made a small function that emits messages via sockets and I am trying to test it using mocha and sinon:

const myFun = socket => {

    socket.emit("first", "hello World!");

    //some random amount of time passes
    socket.emit("second", "hello Moon!");

    //other random amount of time passes
    socket.emit("third", "hello Mars? Venus? I dunno...");
};

使用sinon我可以将一个fakeSocket传递给我的函数:

Using sinon I can pass to my function a fakeSocket:

const fakeSocket = {
    emit: sinon.spy()
};

检查我是否发出消息.

这里的问题是我不知道我的考试何时结束.因为myFun不返回承诺并且我没有 final 消息,所以我不知道如何告诉mocha我已经发送了所有想要的消息,并且测试应该结束.

The problem here is that I don't know when my test ends. Because myFun does not return a promise and I don't have a final message I don't know how to tell mocha that I have sent all the messages I wanted and that the test should end.

const chai = require("chai");
const expect = chai.expect;
const chaiAsPromised = require("chai-as-promised");
chai.use(chaiAsPromised);
const sinon = require("sinon");
const sinonChai = require("sinon-chai");
chai.use(sinonChai);

describe("myFun", () => {

    const fakeSocket = {
            emit: sinon.spy()
        };

    it("receive first message", done => {

        myFun(fakeSocket);

        setTimeout(() => {
            try{
                expect(fakeSocket.emit).to.have.been.calledThrice;
                done();
            }catch(err){
                done(err);
            }
        }, 1000);
        //1 seconds should be more than enough to let the test complete.
    });

});

我正在使用setTimeouttry catch来测试代码,说实话这很可怕.

I am using a setTimeout with a try catch to test the code, which honestly is quite horrible.

  • 如何重新进行测试,以免不依赖setTimeout?

推荐答案

如果您知道总是在最后设置一条特定的消息,则可以在发出该消息时指示Sinon调用函数.该函数可以是Mocha用于异步测试的回调函数:

If you know that a particular message is always set last, you can instruct Sinon to call a function when that message is emitted. That function can be Mocha's callback function for asynchronous tests:

describe("myFun", function() {
  // Extend timeout and "slow test" values.
  this.timeout(3000).slow(10000);

  const fakeSocket = { emit: sinon.stub() }

  it('should emit a certain final message', done => {
    fakeSocket.emit.withArgs('third', 'hello Mars? Venus? I dunno...')
                   .callsFake(() => done());
    myFun(fakeSocket);
  });
});

因此,如果使用参数'third', 'hello Mars?...'调用socket.emit(),则Sinon将调用一个函数,该函数调用done回调,向Mocha表示测试已完成.

So if socket.emit() is called with arguments 'third', 'hello Mars?...', Sinon will call a function that calls the done callback, signalling to Mocha that the test has completed.

由于某种原因未发出该特定消息时,done永远不会被调用,并且测试将超时(3秒后),这表明测试失败或花费了更多时间比预期的要好.

When, for some reason, that particular message isn't emitted, done never gets called and the test will time out (after 3s), which is an indication that either the test has failed, or it took more time than expected.

如果您不知道socket.emit()的第一个参数是最后一条消息,仅消息本身,则测试将变为:

If you don't know what the first argument to socket.emit() is going to be for the last message, only the message itself, the test becomes this:

it('should emit a certain final message', done => {
  fakeSocket.emit.callsFake((name, msg) => {
    if (msg === 'hello Mars? Venus? I dunno...') {
      done();
    }
  });
  myFun(fakeSocket);
})

这篇关于使用Mocha和sinon测试异步功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆