Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test that a function has been called after an event was fired?

There is custom event fired in the FooView ..

// views/foo_view.js

this.trigger("something:happened");

The associated FooController binds a handler to take care of the event ...

// controller/foo_controller.js

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

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

To test the event handling I would write the following test for 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();
});

Though, the test fails ..

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)

Does the test fail because the event takes longer than the expectation to excute?

like image 879
JJD Avatar asked Aug 19 '13 19:08

JJD


People also ask

How do you check if an event is fired?

Open Google Chrome and press F12 to open Dev Tools. Go to Event Listener Breakpoints, on the right: Click on the events and interact with the target element. If the event will fire, then you will get a breakpoint in the debugger.

How do you check if a function has been called in Jasmine?

In the hook, we call the spyOn method to stub the setBar method and then watch how it's called and the result. We can use the toHaveBeenCalled matcher to check if the function is called. Also, we can use toHaveBeenCalledTimes to check how many times it's been called.


1 Answers

The problem is that you spy on a function after the function was bound to the event. When jasmine create a spy it will replace the function you spy on with another function.

So what happens here, is that the original function is bound to the event

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

After that, the original function is replaced by the spy, but that will not have any effect on the function you pass to the bind function.

The solution for that is to spy FooController.prototype.onSomethingHappened before you create a new instance:

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();
});
like image 58
Andreas Köberle Avatar answered Oct 12 '22 23:10

Andreas Köberle