这是我的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语句。

最佳答案

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

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

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

此外,我建议您通过将commInterface调用中的afterEach设置为undefinednull来清理它–只是为了确保每次测试都拥有一个全新的,完全干净的CommunicationInterface实例案件。

希望这可以帮助!

09-19 06:47