あるオブジェクト/関数が、また別のオブジェクト/関数に依存していることは普通にあります。
ユニットテストのときは、実際の依存先オブジェクトではなく、スタブやタプル、モックと呼ばれるダミーのオブジェクトを使います。
jasmineでは、このダミーのオブジェクトをSpyと呼んでいます。これはそのSpyの使い方メモです。

Spyを準備する

Spy関数を作る


const spyFunc = jasmine.createSpy('関数名');

Spy関数を作成します。
関数名はなんでもよいです。

Spyメソッドを持ったオブジェクトを作る


const spyObj = jasmine.createSpyObj('クラス名', [ 'method1', 'method2', ... ]);

method1method2というメソッドを持ったSpyオブジェクトを作成します。
クラス名はなんでもよいです。

既存オブジェクトにSpyプロパティを作る


const spyObj = {};
spyOnProperty(spyObj, 'property1', 'get');
const spySetProp = spyOnProperty(spyObj, 'property1', 'set');

property1という名前のSpyプロパティをspyObjに作成しています。
第3引数のget/setは、値を入出力する方向です。

Spyの振る舞いを定義する

戻り値を設定する


spy.and.returnValue('hoge');

戻り値を'hoge'にしています。

メソッドの場合はこのようになります。


spyObj.method1.and.returnValue('hoge');

複数回呼ばれたときの戻り値をそれぞれ設定する


spy.and.returnValues('hoge', 'fuga', 'fugo');

1回目の戻り値は'hoge'、2回目の戻り値は'fuga'、3回目の戻り値は'fugo'にしています。

例外を発生させる


spy.and.throwError('Error message');

コールバック関数を呼び出す


// 例)第1引数がコールバック関数だった場合
spy.and.calls.first().args[0](コールバック関数の引数);

first()は、関数の初回呼び出しを意味します。
最後の呼び出しの場合は、mostRecent()を使います。


spy.and.calls.mostRecent().args[0](コールバック関数の引数);

複数回呼び出される時の回数を指定する場合は、all()に添字をつけます。


spy.and.calls.all()[2].args[0](コールバック関数の引数);

全体としての例はこんな感じです。


// テスト対象のクラス
class Timeouter {
    constructor(timeout) {
        this._timeout = timeout;
    }

    echoAfter10Secocnds() {
        this._timeout((message) => console.log(message), 10);
    }
}

// テストコード
const timeout = jasmine.createSpy('timeout');
const instance = new Timeouter(timeout);

instance.echoAfter10Seconds();
timeout.calls.first().args[0]('Hello.'); // 初回呼び出し
timeout.calls.all()[1].args[0]('I am Jasmine.'); // 2回目の呼び出し
timeout.calls.mostRecent().args[0]('See you again.'); // 最後の呼び出し

テストの方法

spyが呼ばれたか


expect(spy).toHaveBeenCalled();

spyが呼ばれなかったか


expect(spy).not.toHaveBeenCalled();

spyが特定の引数で呼ばれたか


expect(spy).toHaveBeenCalledWith(期待する引数);

spyが何らかの引数で呼ばれたか


expect(spy).toHaveBeenCalledWith(jasmine.any(期待する引数の型));

// 例)Number型の場合
expect(spy).toHaveBeenCalledWith(jasmine.any(Number));

nullあるいはundefined以外の引数で呼ばれたか


expect(spu).toHaveBeenCalledWith(jasmine.anything());

spyがn回呼ばれたか


// 例)2回呼ばれたか
expect(spy).toHaveBeenCalledTimes(2);

spyがn回目に特定の引数で呼ばれたか

expectを複数個並べればよいです。


expect(spy).toHaveBeenCalled();
expect(spy).toHaveBeenCalled();
expect(spy).toHaveBeenCalledWith(期待する引数);