摩卡 - 我应该直接在describe()块中或之前()内部初始化存根

时间:2018-02-15 15:39:14

标签: node.js express mocha sinon

我需要对存根变量的引用,以便我可以在reset()restore()回调中afterEach()after()

我最初的方法是在describe()块中定义存根,以便可以在回调中访问变量:

describe('my SUT', () => {
  const myStub = sinon.stub(myModule, 'itsMethod');

  after(() => {
    myStub.restore();
  });
});

但是,我想知道使用before()回调进行初始化是否有好处(我还不知道):

describe('my SUT', () => {
  let myStub = null;

  before(() => {
    myStub = sinon.stub(myModule, 'itsMethod');
  });

  after(() => {
    myStub.restore();
  });
});

使用第二种方法有什么好处(如果出现问题,可能还有更多输出等等)?

如果是这样的话,在开始时有很多let myVar = null,任何其他方法都会出错?

2 个答案:

答案 0 :(得分:0)

执行顺序可能存在问题。

问题是描述块的主体在任何beforeafterit块之前执行。

假设我们有一个带有2种方法的api,我们将它们存在于2个不同的describe中:

const sinon = require('sinon');

const api = {
    getFoo() { console.log('executed Foo') },
    getBar() { console.log('executed Bar') }
};

describe('spec 1', () => {
    const stub = sinon.stub(api, 'getFoo').callsFake(() => {console.log('executed Foo stub')});
    console.log('Replaced getFoo with a stub');

    it('test 1', () => {
        console.log('running test 1');

        // We expect a stub to be executed here.
        api.getFoo();
        // We expect an actual method here.
        // But IN FACT we are executing a stub from the next describe block.
        api.getBar();
    });

    after(() => stub.restore());
});

describe('spec 2', () => {
    const stub = sinon.stub(api, 'getBar').callsFake(() => {console.log('executed Bar stub')});
    console.log('Replaced getBar with a stub');

    it('test 2', () => { console.log('running test 2'); });

    after(() => stub.restore());
});

/* Replaced getFoo with a stub
Replaced getBar with a stub
spec 1
running test 1
executed Foo stub
executed Bar stub */

正如您所看到的,我们在第一次测试开始之前已经应用了两个存根。这是一种不确定的行为。

要解决任何问题并清除代码,您可以使用sinon sandboxes + beforeafter块(或者在每个/之后)。

一切都将以正确的顺序存根/取消存在+一个存根可以包含无限量的存根/间谍/等,并且可以在镜头中恢复。

const sandbox = sinon.createSandbox();

describe('spec 1', () => {
    before(() => {
        sandbox.stub(api, 'getFoo').callsFake(() => { console.log('executed getFoo stub'); });
    });

    after(() => sandbox.restore());

    it('test 1', () => {
        // ...
    });
});

他们也在文档中给出了一个很好的例子。

答案 1 :(得分:0)

我建议使用beforeEachafterEach代替beforeafter来创建和清理大多数存根和间谍。

当然,这取决于具体情况 - 如果您的it区块中只有一个describe,则没有任何区别。但是如果你这样做,通常每个测试都有更好的存根副本。这样你就可以在不依赖于其他测试的每个测试中针对存根状态(其调用计数,调用args等)编写断言。