【问题标题】:Javascript sinon.js spy working in one test case but not in otherJavascript sinon.js 间谍在一个测试用例中工作,但在其他测试用例中不工作
【发布时间】:2015-04-21 14:59:38
【问题描述】:

这是我的 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 语句已打印出来。

【问题讨论】:

    标签: javascript node.js sinon


    【解决方案1】:

    乍一看,我认为问题在于您的间谍正在查看commInterface.__proto__.heartBeat,这意味着您断言CommunicationInterface上的heartBeat方法原型是叫。这不会发生,因为当你让 sinon 的时钟滴答作响时,heartBeat 调用是在你在beforeEach 中创建的commInterface instance 上。

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

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

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

    希望这会有所帮助!

    【讨论】:

    • 嗨@grammar,感谢您的回复。另一个相关的问题是var spyHeartBeat = sinon.spy(commInterface, 'heartBeat') 没有在函数上创建间谍,这很奇怪。从console.log 输出我可以看到它正在被调用。因此,要么未正确创建间谍,要么无法检测到从setInterval 调用它。我也在清理commInterface 中的afterEach,但它没有按预期工作。感谢您的宝贵时间。
    • 感谢您的帮助。我可以通过将clock 移动到beforeEach 并使用sinon.sandbox 来解决此问题。
    • 啊,是的,沙盒是我的下一个建议。这样你就可以完全控制时钟、间谍和其他任何东西。很高兴你能够让它工作:)
    猜你喜欢
    • 2012-05-21
    • 1970-01-01
    • 2019-07-21
    • 2021-07-25
    • 1970-01-01
    • 2018-12-15
    • 2014-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多