javascript – QUnit,Sinon.js和Backbone单元测试挫折:sinon间谍似乎未能检测到Backbone Model事件回调

前端之家收集整理的这篇文章主要介绍了javascript – QUnit,Sinon.js和Backbone单元测试挫折:sinon间谍似乎未能检测到Backbone Model事件回调前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在以下单元测试代码中:
  1. TestModel = Backbone.Model.extend({
  2. defaults: {
  3. 'selection': null
  4. },initialize: function() {
  5. this.on('change:selection',this.doSomething);
  6. },doSomething: function() {
  7. console.log("Something has been done.");
  8. }
  9. });
  10.  
  11. module("Test",{
  12. setup: function() {
  13. this.testModel = new TestModel();
  14. }
  15. });
  16.  
  17. test("intra-model event bindings",function() {
  18. this.spy(this.testModel,'doSomething');
  19. ok(!this.testModel.doSomething.called);
  20. this.testModel.doSomething();
  21. ok(this.testModel.doSomething.calledOnce);
  22. this.testModel.set('selection','something new');
  23. ok(this.testModel.doSomething.calledTwice); //this test should past,but fails. Console shows two "Something has been done" logs.
  24. });

第三个ok失败,即使该函数是从主干事件绑定中有效调用的,如控制台演示的那样.

这非常令人沮丧,并且让我对sinon.js是否适合测试我的骨干应用程序感到震惊.我做错了什么,或者这是一个问题,sinon如何检测是否已经调用了某些东西?有解决方法吗?

编辑:这是我的具体例子的解决方案,基于接受答案的猴子补丁方法.虽然它在测试中有几行额外的设置代码,(我不再需要模块功能)但它完成了工作.谢谢,亩太短了

  1. test("intra-model event bindings",function() {
  2. var that = this;
  3. var init = TestModel.prototype.initialize;
  4. TestModel.prototype.initialize = function() {
  5. that.spy(this,'doSomething');
  6. init.call(this);
  7. };
  8.  
  9. this.testModel = new TestModel();
  10. . . . // tests pass!
  11. });

解决方法

调用this.spy(this.testModel,’doSomething’)用 new wrapper method替换testModel.doSomething方法

var spy = sinon.spy(object,“method”);

Creates a spy for object.method and replaces the original method with the spy.

所以this.spy(this.testModel,’doSomething’)实际上是这样做的:

  1. var m = this.testModel.doSomething;
  2. this.testModel.doSomething = function() {
  3. // Spying stuff goes here...
  4. return m.apply(this,arguments);
  5. };

这意味着在initialize中绑定事件处理程序时,testModel.doSomething是一个不同的函数

  1. this.bind('change:selection',this.doSomething);

在你附上间谍之后. Backbone事件调度程序将调用原始的doSomething方法,但该方法没有Sinon检测.当您手动调用doSomething时,您将调用间谍添加的新函数,并且该函数具有Sinon检测.

如果你想使用Sinon测试你的Backbone事件,那么你必须安排在绑定任何事件处理程序之前将Sinon间谍调用应用于模型,这可能意味着挂钩初始化.

也许你可以修补模型的初始化,以便在绑定任何事件处理程序之前添加必要的间谍调用

  1. var init = Model.prototype.initialize;
  2. Model.prototype.initialize = function() {
  3. // Set up the Spy stuff...
  4. init.apply(this,arguments);
  5. };

演示:http://jsfiddle.net/ambiguous/C4fnX/1/

您还可以尝试使用以下内容对您的模型进行子类化:

  1. var Model = Backbone.Model.extend({});
  2. var TestModel = Model.extend({
  3. initialize: function() {
  4. // Set up the Spy stuff...
  5. Model.prototype.initialize.apply(this,arguments);
  6. }
  7. });

然后使用TestModel而不是Model,这将在TestModel中为您提供一个检测版本的Model,而不必在正常的生产就绪模型中包含一堆特定于测试的代码.缺点是使用Model的任何其他东西都需要进行子类化/修补/ …以使用TestModel.

演示:http://jsfiddle.net/ambiguous/yH3FE/1/

您可以通过以下方式解决TestModel问题:

  1. var OriginalModel = Model;
  2. Model = Model.extend({
  3. initialize: function() {
  4. // Set up the Spy stuff...
  5. OriginalModel.prototype.initialize.apply(this,arguments);
  6. }
  7. });

但你必须得到正确的订购,以确保每个人都使用新模型而不是旧模型.

演示:http://jsfiddle.net/ambiguous/u3vgF/1/

猜你在找的JavaScript相关文章