Emberに限った話でもないですが、少しハマったので
はじめに
以下のようなモデルがあるとします
App.User = DS.Model.extend({
name: DS.attr('string'),
age: DS.attr('number'),
callUp: function() {
var calling = this.store.createRecord('calling', userId: this.get('id'));
calling.save().then(function() {
this.store.deleteRecord(calling);
}.bind(this));
}
});
App.Calling = DS.Model.extend({
userId: DS.attr('number')
});
App.User#callUpを実行するとApp.Callingモデルを作成し即座にsaveした後に削除を行います。
こうすることで、POST /callings
なXHRが飛ぶのでRESTfulなAPIでユーザーを呼び出すという動作を行えるようになります。
モデルのunit test
さてcallUpメソッドのテストは以下のように書きました(ember-mochaを使っています)
describeModel('uesr', 'User', {
needs: [],
beforeSetup: function() {}
}, function() {
beforeEach(function() {
this.model = this.subject();
})
describe(function() {
beforeEach(function() {
Ember.run(function() {
this.fakePromise = { then: function(callback) { callback() } };
this.fakeCalling = { save: function() { return this.fakePromise }.bind(this) };
sinon.stub(this.model.store, 'createRecord')
.withArgs('calling', { userId: 0 })
.returns(this.fakeCalling);
sinon.stub(this.model.store, 'deleteRecord')
.withArgs(this.fakeCalling);
this.model.set('id', 0)
}.bind(this))
})
it('should create new calling and delete', function() {
Ember.run(function() {
this.model.callUp();
expect(this.model.store.createRecord.called).to.be.ok
expect(this.model.store.deleteRecord.called).to.be.ok
}.bind(this))
})
})
})
これでstoreオブジェクトを使ってApp.Callingをcreateしてsaveしてdelete...という流れがテストできるようになります。
this.model(this.subject()の戻り値)がundefined
しかしこの後に更に別のテストを追加するとthis.model
はundefinedになってしまいます。
なんでだぁぁぁぁぁぁああ、と思ってよくよくコードを見直すと
sinon.stub(this.model.store, 'createRecord')
この時点でstore.createRecord
は使えない子になってるわけですよね。
しかも特定の引数の場合のみ戻り値を設定しているので、それ以外はundefinedが返るはずです。
this.subject()って中でstore.createRecordを呼び出しているんです。
テストの一番最初のbeforeEachでthis.modelにthis.subject()の戻り値をセットしなおしているので、callUpのテストの後は全てundefinedがthis.modelにセットされるようになるわけです。
sinon.stubしたらrestore
要は戻せばいいだけ
afterEach(function() {
this.model.store.createRecord.restore();
this.model.store.deleteRecord.restore();
})
ドキュメントに書いてあるよね
http://sinonjs.org/docs/#stubs