Best way to test that an event was fired?

2,481 views
Skip to first unread message

Sean Durham

unread,
Apr 12, 2011, 1:58:09 AM4/12/11
to jasmi...@googlegroups.com
Hey all,

I need to test that my object will fire an event when it reaches a state.

Imagine I had an object with a counter property, and a method to increment the counter.
When the counter reaches 2, the object should fire an event of the type "complete", 
so another part of the app can respond.

Here's the test code I wish would pass:

it('should fire an event when it has counted to it's goal', function(){
  var el = $('.counter_value')  // dom element where count is displayed and event is fired.
  var goal = 2; // Counter will fire an event when it has been incremented to reach this number.
  var counter = new Counter( goal, el ); // make a new counter with our element and goal

  counter.increment(); // Counter.value is 1
  counter.increment(); // Counter.value is 2

  // At this point, Counter should fire a 'complete' event, having counted to it's goal.

  expect().toHaveBeenCalled();  // what goes here?
  

});

Davis Frank

unread,
Apr 12, 2011, 2:14:16 AM4/12/11
to jasmi...@googlegroups.com, Sean Durham
So much easier to see what you were talking about when there's code in front of my face.

Here's the challenging question: How would you test this if you didn't have jQuery and DOM?

The point being that you don't need to test jQuery at all. And events are hard to test. So test everything *but* the event code. And then test that you can wire up an element properly.

Does that help?

--dwf





--
You received this message because you are subscribed to the Google Groups "Jasmine" group.
To post to this group, send email to jasmi...@googlegroups.com.
To unsubscribe from this group, send email to jasmine-js+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/jasmine-js?hl=en.

Nicolas Dermine

unread,
Apr 12, 2011, 2:07:55 AM4/12/11
to jasmi...@googlegroups.com

Hi,

If the event fired is a method call, you can spy on that method and expect it to have been called.

hth,
nico

Rajan Agaskar

unread,
Apr 12, 2011, 7:28:48 AM4/12/11
to jasmi...@googlegroups.com, Davis Frank, Sean Durham
I think events can be unit-tested appropriately and simply. The way I see it you have two options:

1) If something you care about behaviorally happens when your counter reaches the goal, you should confirm that that thing happens. For example, counter is a widget whose only behavior is that the complete event pops up an alert when it hits the complete, but you don't care about anything else -- you don't care *how* the alert pops up (ie, that it's triggered by an event), just that it happens. Here, I would spy on window.alert and verify it had been called.  
2) If Counter's behavior is to throw a complete event on some element and this is what you care about (seems like the case here), I would listen on that element for that event to be thrown and verify that it happens. IE, something like (sorry, haven't tested in browser):

var goal = 2;
var el = $(".some-el");
var completeSpy = jasmine.createSpy("completeEventSpy);

var counter = new Counter( goal, el );
$(el).bind("complete", completeSpy);
expect(completeSpy).not.toHaveBeenCalled();
counter.increment();
expect(completeSpy).not.toHaveBeenCalled();
counter.increment();
expect(completeSpy).toHaveBeenCalled();


Thanks!

Rajan

Sean Durham

unread,
Apr 12, 2011, 3:14:27 PM4/12/11
to jasmi...@googlegroups.com, Sean Durham
I think of the event firing as I would the return value of a method—it's the interface other bits will be coded against—so I think it's important to test. If I were not to test it, it would be because I can't, or it's hard, or the tools aren't there yet, not because I don't think I should. Ignoring the event is not my first choice.

Testing that another object responds to the event really is integration testing. It's a step removed. It depends on an unrelated actor to pass. Smells funny.

Maybe the problem is my approach. An odorous aspect of my object is that I'm using a dom element as a crutch to fire events. "Complete"-ness is a state of my JS object, not really to the element I'm using to present it. In my magical dream world I would have my JS object fire the event, I'm borrowing an element to do it.

When you write OOJS without a DOM, do you work without using events? Do you use a framework or roll your own observer pattern implementation?
When you have a DOM at hand, do you piggyback on dom elements for data and state-related events?

Thanks,
–Sean

Sean Durham

unread,
Apr 12, 2011, 3:20:08 PM4/12/11
to jasmi...@googlegroups.com, Davis Frank, Sean Durham
Rajan,

Thanks for the reply. You're right that I am thinking about it the way you explained in your second example. I wasn't successful in my first attempt at using jasmine spy's to test this, but I may have not understood how they work. I'll take another look with your example.

I ended up using jasmine-jquery matchers to make my test pass.

Thanks,
–Sean

Krystian Sowinski

unread,
Mar 6, 2016, 1:51:35 PM3/6/16
to Jasmine, dwf...@pivotallabs.com, se...@sdurham.net


window.alert(“test”) window.alert(“test”)window.alert(“test”)

Gerard Sans

unread,
Mar 7, 2016, 8:52:53 AM3/7/16
to Jasmine
Where is your event API? Node EventEmitter? Or is it a custom event like in https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events?

I'd use a spy or register an event handler setting some value that I can check against.

Reply all
Reply to author
Forward
0 new messages