我有一个名为Feature的类,它包含以下方法setUser(boolean),execute(),doExecute() 并且根据下面描述的参数,当我调用execute()方法时,doExecute()方法应该只被调用一次。
我尝试测试doExecute()方法在下面的代码中仅使用sinon调用一次,但是我收到一条错误消息:doExecute()方法被调用为零次。
请让我知道如果正确调用doExecute()一次是否正确检查
码:
t.context.clock = sinon.useFakeTimers();
const domain = 'testDomain';
const delayInMillis = 0;
const delayInSecs = delayInMillis / 1000;
const feature = new Feature(domain, delayInMillis);
feature.setUser(false);
const p = feature.execute()
.then(() => sinon.spy(feature.doExecute()))
.then(() => t.pass());
sinon.assert.callCount(sinon.spy(feature.doExecute()),1);
t.context.clock.restore();
return p;
});
答案 0 :(得分:0)
首先,sinon.spy()
接受function
作为参数,然后传递函数的结果。
// wrong
sinon.spy(feature.doExecute());
// correct
sinon.spy(feature.doExecute);
接下来,您需要将间谍存储到变量中以供日后参考。在你的代码中,你每次只是创造新的间谍。
const featureDoExecuteSpy = sinon.spy(feature.doExecute);
// some code
sinon.assert.callCount(featureDoExecuteSpy, 1);
答案 1 :(得分:0)
这有很多问题。
正如他所指出的那样,你只是在你的断言中创建一个新的间谍。显然,新间谍的呼叫计数为零。您需要确保断言是指与正在测试的代码调用的相同的间谍实例。
然而,同样错过的关键是,间谍必须传递给你正在测试的代码。这就是为什么`sinon.spy()'的usual form接受一个对象后跟一个方法名称的原因。它用一个封装原始对象的间谍替换该对象上的方法:// wrong
sinon.spy(feature.doExecute());
// still wrong
sinon.spy(feature.doExecute);
// correct
sinon.spy(feature, 'doExecute');
然后,您可以访问该对象上的间谍以进行断言。您无需将其存储在本地变量中:
sinon.assert.callCount(feature.doExecute, 1);
另一个问题:您的断言不等待feature.execute
解决的承诺。这意味着如果在doExecute
内的某些异步操作之后调用execute
,则您的断言发生得太早。因此,它需要在then
后跟其他人一样(请注意,由于我稍后会解决的其他问题,此代码仍然无效):
const p = feature.execute()
.then(() => sinon.spy(feature, 'doExecute'))
.then(() => t.pass())
.then(() => sinon.assert.callCount(feature.doExecute,1));
更多问题......您使用假定时器非常奇怪,并且我很难判断feature.execute()
返回的承诺是否会解决。
如果需要计时器才能解决?它不会。因为你永远都不会打电话给计时器。我不知道t.pass()
做了什么,但由于它被链接到feature.execute()
返回的承诺,如果你不在其他地方勾选计时器,它将永远不会被调用。由于同样的原因,你的代码也不会造成你的间谍。
你需要在调用feature.execute()
之前创建你的间谍,并且可能在之后调用t.pass()
,如果它确实是勾选你的方法假计时器:
sinon.spy(feature, 'doExecute')
const p = feature.execute()
.then(() => sinon.assert.callCount(feature.doExecute,1));
t.pass();
最后,我不知道你正在使用什么测试框架,但是你通常希望在总是执行的块中恢复假定时器和其他全局状态,无论你的测试是否成功。这样可以确保失败的测试不会让废话悬挂在其他测试中。为此,Mocha有方法beforeEach
和afterEach
:
beforeEach(function() {
t.context.clock = sinon.useFakeTimers();
});
afterEach(function() {
t.context.clock.restore()
});
it('whatever your test name is', function() {
const domain = 'testDomain';
const delayInMillis = 0;
const delayInSecs = delayInMillis / 1000;
const feature = new Feature(domain, delayInMillis);
sinon.spy(feature, 'doExecute')
const p = feature.execute()
.then(() => sinon.assert.callCount(feature.doExecute,1));
t.pass();
return p;
});