Reputation: 4067
I am wondering what is the correct approach. First here is the test code.
describe 'Something', ->
it 'should trigger event', (done) ->
spy = sinon.spy()
instance = new Something()
instance.on("itsdone", spy)
instance.methodCall()
spy.should.have.been.calledOnce
done()
Looks pretty straightforward, but since events are usually asynchronous, this cannot work.
class Something
constructor: ->
@events = {}
on: (event, cb) ->
@events[event] = new signals.Signal() unless @events[event]?
@events[event].add cb
methodCall: ->
# Fire up `itsdone` event when everything else is done
setTimeout (=> @events['itsdone']?.dispatch()), 0
This way test will fail obviously. Then I thought about something like this...
describe 'Something', ->
it 'should be triggering even', (done) ->
instance = new Something()
instance.on("itsdone", done)
instance.methodCall()
This works correctly and when event is not triggered, test will fail after 2 seconds. However there is no verification, that it was triggered only once. Maybe I need another test for that ? Since I already know it's triggered at least once, I can use test with spy after this one probably. Although it seems too much hassle for one event.
Another "dirty" approach could be this:
describe 'Something', ->
it 'should be triggering even', (done) ->
spy = sinon.spy()
instance = new Something()
instance.on("itsdone", spy)
instance.methodCall()
setTimeout ->
spy.should.have.been.calledOnce
done()
, 0
It isn't probably really bulletproof. It would need bigger timeout probably to be sure. However that means tests will take longer to process, which is not good idea.
Do you have any other ideas how this should be solved ?
Upvotes: 3
Views: 972
Reputation: 19879
I think your third choice is the right one:
describe 'Something', ->
it 'should be triggering even', (done) ->
instance = new Something()
instance.on("itsdone", done)
instance.methodCall()
If I understand correctly, your concern is that this doesn't test that the callback is not called twice.
In general it is difficult to test that things don't happen. For example, how long are you going to wait to see if it isn't called a second time? 2 seconds? 2 hours? You really need to use your understanding of the code being tested to know what tests are needed. Unit testing shouldn't be complete black-box testing.
I wouldn't test that it isn't called twice unless I know that the underlying code might break in a way that would cause it to be called twice.
Upvotes: 2