ハマったコード
下記のcoffeescriptのコードをjsTestDriverでテストします。なお私の場合Backbone.jsを使ってハマりましたが、基本的にはjQueryのonでも同じ結果になると思われます。
class @EventSample
constructor: ->
@func = null
Backbone.on("test", => @.onTest())
onTest: ->
@func()
テストコードは下記です。
TestCase "Test1",
setUp: ->
@event = new EventSample()
"test1": ->
assertNull(@event.func)
TestCase "Test2",
setUp: ->
@event = new EventSample()
@event.func = ->
console.log "dummy"
"test2": ->
Backbone.trigger "test"
assertNotNull(@event.func)
- Test1はクラスを初期化して、@funcがnullであることを確認するだけのテストです。
- Test2は@funcに適当に関数を設定して、イベント"test"を発行するテストです。@func()が実行されるはずです。
どうハマったか
上記のテストを実行すると、Test2でなぜか@funcがnullで実行できないというエラーが発生します。
原因
Test2の実行時もTest1で生成した@eventのインスタンスが残っているのが原因。イベント"test"を発行すると、Test1, Test2両方の@eventのonTest()が実行される。Test1の@event.funcはnullなので当然関数としては実行できずエラーとなってしまう。
解決方法
下記のように、onで登録したイベントを解除する関数を追加する。
class @EventSample
constructor: ->
@func = null
Backbone.on("test", => @.onTest())
#追加
unbindEvent: ->
Backbone.off("test")
onTest: ->
@func()
テストでは、 tearDownで登録したイベントを解除 します。
TestCase "Test1",
setUp: ->
@event = new EventSample()
tearDown: ->
@event.unbindEvent()
"test1": ->
assertNull(@event.func)
TestCase "Test2",
setUp: ->
@event = new EventSample()
@event.func = ->
console.log "dummy"
tearDown: ->
@event.unbindEvent()
"test2": ->
Backbone.trigger "test"
assertNotNull(@event.func)