Javascript sinon.js间谍在一个测试用例中工作但在其他测试用例中没有

时间:2015-04-21 14:59:39

标签: javascript node.js sinon

这是我的javascript类

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语句。

1 个答案:

答案 0 :(得分:2)

乍一看,我认为问题在于你的间谍正在查看commInterface.__proto__.heartBeat,这意味着你在heartBeat 上断言CommunicationInterface方法原型被调用。这不会发生,因为当您使用sinon的时钟时,heartBeat调用位于您在commInterface内创建的beforeEach 实例。< / p>

这可以通过实际监视实例上的heartBeat而不是原型来解决,如下所示:

var spyHeartBeat = sinon.spy(commInterface, 'heartBeat');

此外,我建议您在commInterface来电中清除afterEach,将其设为undefinednull - 只是为了确保您拥有一个全新的,每个测试用例都完全清除CommunicationInterface的实例。

希望这有帮助!