Javascript sinon.js 间谍在一个测试用例中工作但在其他测试用例中不工作
Javascript sinon.js spy working in one test case but not in other
这是我的javascriptclass
var CommunicationInterface = inherit(Interface, {
__constructor: function() {
this.heartBeatDuration = 60 * 1000;
this.client = null;
this._isSetupped = false;
this.__base();
},
setup: function() {
// console.log('xmpp interface setup started');
var _this = this;
var deferred = Q.defer();
if (this._isSetupped) {
deferred.resolve();
return deferred.promise;
}
CommConfig.get('params')
.then(function(params) {
_this.client = new Client({
id: params.id + '@' + config('HOST'),
password: params.password,
host: config('HOST'),
port: config('PORT'),
reconnect: true
});
_this.client.on('online', _this.onOnline.bind(_this));
setInterval(function() {
_this.heartBeat.bind(_this)(params.id);
}, _this.heartBeatDuration);
_this._isSetupped = true;
deferred.resolve();
}, function(err){
console.log(err);
});
return deferred.promise;
},
heartBeat: function(Id) {
var stanza = this._makeMessage({
'to': id + '@' + config('HOST'),
'type': 'chat'
}, '{}');
console.log('foo');
this.client.send(stanza);
console.log('bar');
},
onOnline: function() {
console.log('online');
this.client.send('online');
this.emitter.emit('online');
},
});
测试代码为:
describe('CommunicationInterface', function() {
var commInterface;
var stubGetConfig, stubCommClient, stubCommClientConnect, spyCommClientSend;
var clock;
before(function () {
var deferred = Q.defer();
stubGetConfig = sinon.stub(CommConfig, 'get')
.withArgs('params')
.returns(deferred.promise);
deferred.resolve({
'id': 'test',
'password': '123456',
});
stubCommClientConnect = sinon.stub(CommunicationInterface.Client.prototype,
'connect');
clock = sinon.useFakeTimers();
});
beforeEach(function () {
commInterface = new CommunicationInterface();
stubCommClient = sinon.spy(commInterface.client);
});
afterEach(function () {
stubCommClientConnect.reset();
stubGetConfig.reset();
stubCommClient.reset();
clock.restore();
});
it('test 1', function(done) {
commInterface.setup()
.done(function () {
var spyCommClientSend = sinon.spy(commInterface.client, 'send');
commInterface.client.emit('online');
assert.isTrue(spyCommClientSend.calledOnce);
assert.isTrue(spyCommClientSend.calledWithExactly('online'));
done();
});
});
it('test 2', function(done) {
var spyHeartBeat = sinon.spy(commInterface.__proto__, 'heartBeat');
commInterface.setup().done(function() {
var spyCommClientSend = sinon.spy(commInterface.client, 'send');
clock.tick(commInterface.heartBeatDuration + 10);
assert.isTrue(spyHeartBeat.calledOnce);
assert.isTrue(spyCommClientSend.called);
spyHeartBeat.restore();
done();
});
});
});
test 1
中的代码工作正常并且 spyCommClientSend
已正确创建,但 test 2
中的第二个断言失败并且 spyCommClientSend
未侦测到实际对象。
这可能是什么原因?
我确定正在调用 send
函数,因为它周围的两个 console.log
语句已打印出来。
乍一看,我认为问题在于你的间谍正在查看 commInterface.__proto__.heartBeat
,这意味着你断言 CommunicationInterface
上的 heartBeat
方法 prototype 被调用。这不会发生,因为当你让 sinon 的时钟滴答作响时,heartBeat
调用是在你在 beforeEach
中创建的 commInterface
实例 上调用的。
这可能会通过实际监视 heartBeat
实例而不是原型来解决,如下所示:
var spyHeartBeat = sinon.spy(commInterface, 'heartBeat');
此外,我建议您通过将 afterEach
调用设置为 undefined
或 null
来清理 commInterface
- 以确保您有一个每个测试用例都有 CommunicationInterface
的全新、完全干净的实例。
希望对您有所帮助!
这是我的javascriptclass
var CommunicationInterface = inherit(Interface, {
__constructor: function() {
this.heartBeatDuration = 60 * 1000;
this.client = null;
this._isSetupped = false;
this.__base();
},
setup: function() {
// console.log('xmpp interface setup started');
var _this = this;
var deferred = Q.defer();
if (this._isSetupped) {
deferred.resolve();
return deferred.promise;
}
CommConfig.get('params')
.then(function(params) {
_this.client = new Client({
id: params.id + '@' + config('HOST'),
password: params.password,
host: config('HOST'),
port: config('PORT'),
reconnect: true
});
_this.client.on('online', _this.onOnline.bind(_this));
setInterval(function() {
_this.heartBeat.bind(_this)(params.id);
}, _this.heartBeatDuration);
_this._isSetupped = true;
deferred.resolve();
}, function(err){
console.log(err);
});
return deferred.promise;
},
heartBeat: function(Id) {
var stanza = this._makeMessage({
'to': id + '@' + config('HOST'),
'type': 'chat'
}, '{}');
console.log('foo');
this.client.send(stanza);
console.log('bar');
},
onOnline: function() {
console.log('online');
this.client.send('online');
this.emitter.emit('online');
},
});
测试代码为:
describe('CommunicationInterface', function() {
var commInterface;
var stubGetConfig, stubCommClient, stubCommClientConnect, spyCommClientSend;
var clock;
before(function () {
var deferred = Q.defer();
stubGetConfig = sinon.stub(CommConfig, 'get')
.withArgs('params')
.returns(deferred.promise);
deferred.resolve({
'id': 'test',
'password': '123456',
});
stubCommClientConnect = sinon.stub(CommunicationInterface.Client.prototype,
'connect');
clock = sinon.useFakeTimers();
});
beforeEach(function () {
commInterface = new CommunicationInterface();
stubCommClient = sinon.spy(commInterface.client);
});
afterEach(function () {
stubCommClientConnect.reset();
stubGetConfig.reset();
stubCommClient.reset();
clock.restore();
});
it('test 1', function(done) {
commInterface.setup()
.done(function () {
var spyCommClientSend = sinon.spy(commInterface.client, 'send');
commInterface.client.emit('online');
assert.isTrue(spyCommClientSend.calledOnce);
assert.isTrue(spyCommClientSend.calledWithExactly('online'));
done();
});
});
it('test 2', function(done) {
var spyHeartBeat = sinon.spy(commInterface.__proto__, 'heartBeat');
commInterface.setup().done(function() {
var spyCommClientSend = sinon.spy(commInterface.client, 'send');
clock.tick(commInterface.heartBeatDuration + 10);
assert.isTrue(spyHeartBeat.calledOnce);
assert.isTrue(spyCommClientSend.called);
spyHeartBeat.restore();
done();
});
});
});
test 1
中的代码工作正常并且 spyCommClientSend
已正确创建,但 test 2
中的第二个断言失败并且 spyCommClientSend
未侦测到实际对象。
这可能是什么原因?
我确定正在调用 send
函数,因为它周围的两个 console.log
语句已打印出来。
乍一看,我认为问题在于你的间谍正在查看 commInterface.__proto__.heartBeat
,这意味着你断言 CommunicationInterface
上的 heartBeat
方法 prototype 被调用。这不会发生,因为当你让 sinon 的时钟滴答作响时,heartBeat
调用是在你在 beforeEach
中创建的 commInterface
实例 上调用的。
这可能会通过实际监视 heartBeat
实例而不是原型来解决,如下所示:
var spyHeartBeat = sinon.spy(commInterface, 'heartBeat');
此外,我建议您通过将 afterEach
调用设置为 undefined
或 null
来清理 commInterface
- 以确保您有一个每个测试用例都有 CommunicationInterface
的全新、完全干净的实例。
希望对您有所帮助!