[Node]Backbone.js + Sinon.js で callback をテストしようとしてハマる
端的に言うと以下のコードは想定通りに動かない。(Node のコンソールで)
var Backbone = require('backbone') var Sinon = require('sinon') var m = new Backbone.Model({ 'foo': 'bar' }) var f = function(){ console.log("===> Callback called") } m.on('change', f) Sinon.spy(this, 'f') m.set('foo', 'hoge') f.called // => false
m.on('change', f) した時点で f の参照自体が m に束縛されていて、その後いくら spy で this.f をすげ替えても、 m のコールバックで呼ばれる処理には影響しない。
その処理以降を次のように変えてやれば動く。
m.on('change', function() { f() }) Sinon.spy(this, f) m.set('foo', 'hoge') m.called // => true
実際に backbone + coffee + mocha で使うときにはこんな感じになる。
# in view class FooView extends Backbone.View initialize: -> _.bindAll @ @model.on 'change', => @render() #.... # in spec (変数定義は適切な場所へ移動すべし) it 'change cases rendering' do model = new Backbone.Model foo: 'bar' view = new FooView model: model render = sinon.spy(view, 'render') model.set('foo', hoge') render.called.should.be.true
あるいは(この例の場合) render の中身の動作を spy してもよいだろう。