第一次测试后 Sinon 存根未 "called"

Sinon stubs not "called" after first test

我正在尝试为我的 socket.io 服务器编写一些基本测试,但我无法将我的测试一起用于 运行。出于某种原因,我的存根在第一个测试中被调用,但在以下检查不同 stubs/spies 的测试中没有被调用。如果更改测试在测试文件中定义的顺序,则先通过的为准。

这是我正在测试的简化模块 (server.js):

var exports = module.exports = {},
    io = require('socket.io')(8080);

function startServer() {
    io.on('connection', function (socket) {
        socket.emit('loading');
    });
};

exports.startServer = startServer;

这是我的测试文件:

var expect = require('chai').expect,
    sinon = require('sinon'),
    mockery = require('mockery');

describe('bidding-war-server', function () {
    var biddingWarServer,
        stubbedIo;

    before(function () {
        mockery.enable();
    });

    beforeEach(function () {
        stubbedIo = {
            on: function() { }
        };
        var mockSocketIo = function (port) {
            return stubbedIo;
        };

        mockery.deregisterAll();
        mockery.registerAllowable('./server');
        mockery.registerMock('socket.io', mockSocketIo);
        biddingWarServer = require('./server');
    });

    after(function () {
        mockery.deregisterAll();
        mockery.disable();
    });

    it('should call socket.emit loading', function () {
        var stubbedSocket = {
            emit: sinon.spy(),
        };
        stubbedIo.on = sinon.stub().callsArgWith(1, stubbedSocket);

        biddingWarServer.startServer();

        expect(stubbedSocket.emit.called).to.be.true;
    });

    it('should setup io.on connection', function () {
        stubbedIo.on = sinon.spy();

        biddingWarServer.startServer();

        expect(stubbedIo.on.called).to.be.true;
    });
});

有人看到我在这里遗漏了什么吗?

此问题源于模块缓存 - 您的 server.js 仅加载一次。

为了解决这个问题,我最终开始分别在 beforeEachafterEach 块中执行 mockery.enablemockery.disable,同时强制 mockery 使用 clean缓存。

请查看更新后的测试文件:

var expect = require('chai').expect,
    sinon = require('sinon'),
    mockery = require('mockery');

describe('bidding-war-server', function () {
    var biddingWarServer,
        stubbedIo;

    beforeEach(function () {
        stubbedIo = {
            on: function() { }
        };
        var mockSocketIo = function (port) {
            return stubbedIo;
        };

        mockery.registerAllowable('./server');
        mockery.registerMock('socket.io', mockSocketIo);
        mockery.enable({useCleanCache: true});

        biddingWarServer = require('./server');
    });

    afterEach(function() {
        mockery.deregisterAll();
        mockery.disable();
    });

    it('should call socket.emit loading', function () {
        var stubbedSocket = {
            emit: sinon.spy(),
        };
        stubbedIo.on = sinon.stub().callsArgWith(1, stubbedSocket);

        biddingWarServer.startServer();

        expect(stubbedSocket.emit.called).to.be.true;
    });

    it('should setup io.on connection', function () {
        stubbedIo.on = sinon.spy();

        biddingWarServer.startServer();

        expect(stubbedIo.on.called).to.be.true;
    });
});