如何测试在事件被触发后调用函数?

时间:2013-08-19 19:53:41

标签: javascript javascript-events asynchronous jasmine spy

FooView ..

中触发了自定义事件
// views/foo_view.js

this.trigger("something:happened");

关联的FooController绑定处理程序以处理事件......

// controller/foo_controller.js

initialize: function() {
  this.fooView = new FooView();
  this.fooView.bind("something:happened", this.onSomethingHappened, this);
}

onSomethingHappened: function(event) {
  // Do something else.
}

为了测试事件处理,我会为Jasmine编写以下测试:

it("should do something else when something happens", function() {
  var fooController = new FooController();
  spyOn(fooController, "onSomethingHappened");
  fooController.fooView.trigger("something:happened");
  expect(fooController.onSomethingHappened).toHaveBeenCalled();
});

虽然,测试失败了..

FooView should do something else when something happens.
Expected spy onSomethingHappened to have been called.
Error: Expected spy onSomethingHappened to have been called.
    at new jasmine.ExpectationResult (http://localhost:8888/__JASMINE_ROOT__/jasmine.js:114:32)
    at null.toHaveBeenCalled (http://localhost:8888/__JASMINE_ROOT__/jasmine.js:1235:29)
    at null.<anonymous> (http://localhost:8888/assets/foo_spec.js?body=true:225:47)
    at jasmine.Block.execute (http://localhost:8888/__JASMINE_ROOT__/jasmine.js:1064:17)
    at jasmine.Queue.next_ (http://localhost:8888/__JASMINE_ROOT__/jasmine.js:2096:31)
    at jasmine.Queue.start (http://localhost:8888/__JASMINE_ROOT__/jasmine.js:2049:8)
    at jasmine.Spec.execute (http://localhost:8888/__JASMINE_ROOT__/jasmine.js:2376:14)
    at jasmine.Queue.next_ (http://localhost:8888/__JASMINE_ROOT__/jasmine.js:2096:31)
    at onComplete (http://localhost:8888/__JASMINE_ROOT__/jasmine.js:2092:18)
    at jasmine.Spec.finish (http://localhost:8888/__JASMINE_ROOT__/jasmine.js:2350:5)

测试是否因为事件花费的时间超过预期执行而失败?

1 个答案:

答案 0 :(得分:17)

问题是在函数绑定到事件后监视函数。当jasmine创建一个间谍时,它将用另一个函数替换你侦察的函数。

所以这里发生的是,原始函数绑定到事件

this.fooView.bind("something:happened", this.onSomethingHappened, this);

之后,原始函数被间谍取代,但这对传递给bind函数的函数没有任何影响。

解决方法是在创建新实例之前监视FooController.prototype.onSomethingHappened

it("should do something else when something happens", function() {
  var onSomethingHappenedSpy = spyOn(FooController.prototype, "onSomethingHappened");
  var fooController = new FooController();
  fooController.fooView.trigger("something:happened");
  expect(onSomethingHappenedSpy).toHaveBeenCalled();
});