我需要对存根变量的引用,以便我可以在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
,任何其他方法都会出错?
答案 0 :(得分:0)
执行顺序可能存在问题。
问题是描述块的主体在任何before
,after
和it
块之前执行。
假设我们有一个带有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 + before
和after
块(或者在每个/之后)。
一切都将以正确的顺序存根/取消存在+一个存根可以包含无限量的存根/间谍/等,并且可以在镜头中恢复。
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)
我建议使用beforeEach
和afterEach
代替before
和after
来创建和清理大多数存根和间谍。
当然,这取决于具体情况 - 如果您的it
区块中只有一个describe
,则没有任何区别。但是如果你这样做,通常每个测试都有更好的存根副本。这样你就可以在不依赖于其他测试的每个测试中针对存根状态(其调用计数,调用args等)编写断言。