オブジェクトなしで関数をスパイするためのジャスミンの使用


154

私はJasmineを初めて使用し、使用を開始しました。どのオブジェクトにも関連付けられていない(つまり、グローバルな)関数がたくさんあるライブラリjsファイルがあります。これらの機能をスパイするにはどうすればよいですか?

オブジェクトとしてwindow / documentを使用してみましたが、関数が呼び出されてもスパイが機能しませんでした。また、次のように偽のオブジェクトでラップしてみました。

var fakeElement = {};
fakeElement.fakeMethod = myFunctionName;
spyOn(fakeElement, "fakeMethod");

とテストする

expect(fakeElement.fakeMethod).toHaveBeenCalled();

スパイが機能しなかったため、これも機能しません

回答:


155

関数を定義している場合:

function test() {};

次に、これは次と同等です。

window.test = function() {}  /* (in the browser) */

だから、spyOn(window, 'test')動作するはずです。

そうでない場合は、次のこともできるはずです。

test = jasmine.createSpy();

これらのいずれも機能していない場合は、セットアップで他の問題が発生しています。

fakeElement裏で何が起こっているのか、あなたのテクニックはうまくいかないと思います。元のglobalMethodはまだ同じコードを指しています。スパイが行うのはプロキシですが、オブジェクトのコンテキストでのみです。fakeElementを介してテストコードを呼び出すことができれば機能しますが、グローバルfnをあきらめることができます。


2
出来た!私が以前に犯していたエラーは、spyOnをmethodではなくmethod()で呼び出していたということでした。ありがとう!
Chetter Hummin 2012年

3
'window'が割り当てられていないため、自動化の一部としてテストを実行するためにchutzpahを使用してspyOn(window、 'test')を使用するときに問題が発生しました。jasmine.createSpy()を使用してこれを回避しました。
Henners 2013

7
jasmine.createSpy()は完璧に動作しました。ありがとう!
dplass 14

1
使用test = jasmine.createSpy();angularJsをスパイするために$anchroScroll完全に働いた
エドガー・マルティネス

1
なんらかの理由でどちらの方法でも機能しない場合がありますが、既存のウィンドウ関数をモックアップしようとしているために、完全に可能である可能性があります。$window.open(url, '_blank');新しいタブ(またはブラウザの設定によってはウィンドウ)を開くことを目的としています。この関数が呼び出されていることを確認し、ブラウザに関係なく正しいURLに移動していることを確認するにはどうすればよいですか?
CSS

71

TypeScriptユーザー:

私はOPがjavascriptについて尋ねたことを知っていますが、これに遭遇してインポートされた関数をスパイしたいTypeScriptユーザーのために、あなたができることがここにあります。

テストファイルで、関数のインポートを次のように変換します。

import {foo} from '../foo_functions';

x = foo(y);

これに:

import * as FooFunctions from '../foo_functions';

x = FooFunctions.foo(y);

次に、あなたはスパイすることができますFooFunctions.foo:)

spyOn(FooFunctions, 'foo').and.callFake(...);
// ...
expect(FooFunctions.foo).toHaveBeenCalled();

3
TypeScriptヒントをありがとう。ES6 / Babelも同じようにする必要がありますが、試したことはありません。
hgoebl 2017年

1
エイリアスFooFunctionsで関数を明示的に呼び出す場合にのみ機能するようです。baz()を返すファクトリである関数bar()があり、baz()がfoo()を呼び出すことをテストしたい。この方法は、このシナリオでは機能しないようです。
Richard Matsen 2017

4
これは、エイリアスがfoo_functions内で取得さ export const FooFunctions = { bar, foo }; れ、テストでのインポート import { FooFunctions } from '../foo_functions'. が次のようになる場合に機能します。ただし、スパイが機能するには、foo_functionsプライベート実装内で明示的にエイリアスを使用する必要があります。 const result = FooFunctions.foo(params)//スパイレポートコールconst result = foo(params)//スパイレポートコールなし
Richard Matsen 2017

2
魅力のように働いた!ありがとう、あなたは私に多くの時間を節約してくれました!
SrAxi 2018年

1
これはもう機能していませんError: <spyOn> : parseCookie is not declared writable or has no setter
Ling Vu

42

私が使用する2つの選択肢があります(ジャスミン2の場合)

関数は実際には偽物であると思われるため、これは明確ではありません。

test = createSpy().and.callFake(test); 

2つ目はより詳細で、より明確で、「よりクリーン」です。

test = createSpy('testSpy', test).and.callThrough();

-> ジャスミンソースコードで 2番目の引数を表示


これはもう少し理にかなっていて、複製して成功するのに十分なほどそれを分割します。私からの+1。おかげで、ć§
CSS

9

非常に簡単な方法:

import * as myFunctionContainer from 'whatever-lib';

const fooSpy = spyOn(myFunctionContainer, 'myFunc');

1
import * as saveAsFunctions from 'file-saver';
..........
....... 
let saveAs;
            beforeEach(() => {
                saveAs = jasmine.createSpy('saveAs');
            })
            it('should generate the excel on sample request details page', () => {
                spyOn(saveAsFunctions, 'saveAs').and.callFake(saveAs);
                expect(saveAsFunctions.saveAs).toHaveBeenCalled();
            })

これでうまくいきました。


4
答えに説明を追加してください。コード自体は、何が起こっているのか理解できない場合、質問をする人にとってそれほど役に立ちません。
chevybow

0

私の回答は、インポートされたモジュールに単一の(デフォルトのエクスポート)関数があったという点で@FlavorScapeとは少し異なります。次のようにしました。

import * as functionToTest from 'whatever-lib';

const fooSpy = spyOn(functionToTest, 'default');
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.