JavaScript BDD/Testing / Jasmine 2.0 - Spy
前回簡単にまとめたんですが、そのとき書いてなかった Jasmine 2.0の Spy関連について。
Spyって何?
Jasmineの Spyを使うとこんな事が出来ます。
- 関数呼び出しの追跡(呼び出し引数をあとで確認、呼び出し回数をカウント等)
- 関数呼び出しを偽装(実際に実行しない、別の関数を実行、例外を投げる等)
- モックの作成
基本的な使い方
関数呼び出しの追跡
関数呼び出しに関する追跡を行います。監視する関数の動作に影響をあたえません。
function Clazz() {
}
Clazz.prototype.method = function (str) {
console.log(str);
};
describe("関数呼び出しの追跡", function() {
var hoge;
beforeEach(function() {
hoge = new Clazz();
// hoge.method() 呼び出しを追跡する //
spyOn(hoge, 'method')<strong>.and.callThrough();</strong>
hoge.method('hoge');
hoge.method('hehe');
});
it("methodが呼びだされた事が確認できます。", function() {
expect(hoge.method).toHaveBeenCalled();
});
it("関数呼び出し時の引数がわかります。", function() {
expect(hoge.method).toHaveBeenCalledWith('hehe');
expect(hoge.method).toHaveBeenCalledWith('hoge');
});
it("関数呼び出し時の引数、呼び出し順序も確認したい場合はこんな感じ", function() {
expect(hoge.method.calls.argsFor(0)).toEqual(['hoge']);
expect(hoge.method.calls.argsFor(1)).toEqual(['hehe']);
});
it("関数呼び出し回数は2回", function () {
expect(hoge.method.calls.count()).toBe(2);
});
});
spyOn(obj, name);
で obj.nameの関数を spy(関数)と置き換える事で追跡が可能になります。
例にある spyOn(object, method_name).and.callThrough();
で、最後の.and.callThrough()は元関数を呼び出すために必要な設定です。これが無い場合はspyは元の関数を呼び出しません。
注意として引数の確認 toHaveBeenCalledWithは 呼び出し順序は無視して比較します。上の例で呼び出しは’hoge’→’hehe’ですが、expectの順序は関係なく’hehe’→’hoge’でも成功となります。
順序も含めて確認したい場合はspyの callsプロパティの argsFor()を使います。
例には含めていませんが、関数が呼ばれた時のthisも確認できます。この場合 .calls.all(), .calls.first(), .calls.mostRecen() を使う。
関数呼び出しの偽装
「関数呼び出しの追跡」時に実際に実行する関数をすり替えます。
すり替える内容によって spyOn()が少し変わります。
// hoge.method() 呼び出しを追跡するだけで 実際にmethodを実行しない。 //
spyOn(hoge, 'method');
// hoge.method() 呼び出しを追跡し、呼び出しの戻り値は'hoge'にする。 //
spyOn(hoge, 'method').and.returnValue('hoge');
// hoge.method() 呼び出しを追跡し、関数の呼び出しをfake_methodにすり替える //
spyOn(hoge, 'method').and.callFake(function fake_method() {return false;});
// hoge.method() 呼び出しを追跡し、関数が呼び出されると Errorを throwする //
spyOn(hoge, 'method').and.throwError("error message");
特記として、spyに対して.and.stub()を行う事で デフォルトのstub関数(実際の関数を呼び出さない)に戻す事が出来る。
たとえばspyOn(hoge, 'method').and.callThrough();
とした後でhoge.method.and.stub();
とすると、
その後のspy関数の呼び出しは実際の関数を呼び出さなくなります。
モックの作成
Spyされた関数を持つモックを作るときには、jasmine.createSpyObj(); を呼び出します。
var mock = jasmine.createSpyObj('mock', ['doThat', 'doThis', ...]);
mock.doThat.and.throwError("I hate to do that.");
mock.doThis.and.returnValue("done.");
mock.doThatや doThisは spyなので 呼び出しがすべて記録されます。
その他
追跡情報をクリアする calls.reset()、spy関数を作成する jasmine.createSpy()があります。resetは使った事ありませんが、createSpyは関数のテストでcallback関数を作成する場合に便利です。