私は正しいアプローチが何であるか疑問に思っています。まずはテストコードです。
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()
非常に単純に見えますが、イベントは通常非同期であるため、これは機能しません。
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
この方法では、テストは明らかに失敗します。すると、こんなことを考えていた…。
describe 'Something', ->
it 'should be triggering even', (done) ->
instance = new Something()
instance.on("itsdone", done)
instance.methodCall()
これは正しく機能し、イベントがトリガーされない場合、テストは 2 秒後に失敗します。ただし、一度だけトリガーされたという検証はありません。多分私はそのために別のテストが必要ですか?少なくとも 1 回トリガーされることは既にわかっているので、おそらくこの後にスパイでテストを使用できます。1つのイベントでは面倒すぎるようですが。
別の「汚い」アプローチは次のとおりです。
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
それはおそらく本当に防弾ではありません。確かに、おそらくより大きなタイムアウトが必要になるでしょう。ただし、これはテストの処理に時間がかかることを意味し、これはお勧めできません。
これをどのように解決すべきか他のアイデアはありますか?