引数に基づいてジャスミンのスパイを変更する方法はありますか?


146

異なるパラメーターを使用して、外部APIメソッドを2回呼び出すテストしたい関数があります。この外部APIをJasmineスパイでモックアウトし、パラメーターに基づいてさまざまなものを返したいのですが。ジャスミンでこれを行う方法はありますか?私が思いつくことができる最高のものはandCallFakeを使ったハックです:

var functionToTest = function() {
  var userName = externalApi.get('abc');
  var userId = externalApi.get('123');
};


describe('my fn', function() {
  it('gets user name and ID', function() {
    spyOn(externalApi, 'get').andCallFake(function(myParam) {
      if (myParam == 'abc') {
        return 'Jane';
      } else if (myParam == '123') {
        return 98765;
      }
    });
  });
});

回答:


213

Jasmineバージョン3.0以降では、 withArgs

describe('my fn', function() {
  it('gets user name and ID', function() {
    spyOn(externalApi, 'get')
      .withArgs('abc').and.returnValue('Jane')
      .withArgs('123').and.returnValue(98765);
  });
});

3.0より前のバージョンのJasmineの場合callFakeは正しい方法ですが、戻り値を保持するオブジェクトを使用して簡略化できます

describe('my fn', function() {
  var params = {
    'abc': 'Jane', 
    '123': 98765
  }

  it('gets user name and ID', function() {
    spyOn(externalApi, 'get').and.callFake(function(myParam) {
     return params[myParam]
    });
  });
});

Jasmineのバージョンによって、構文は少し異なります。

  • 1.3.1: .andCallFake(fn)
  • 2.0: .and.callFake(fn)

リソース:


11
これは今あるand.callFake- jasmine.github.io/2.2/... >
ルーシー・ベイン

私は異なるプロミスを返す必要があったので、戻りは少し異なって見えました:return q.when(params [myParam]);。そうでなければ、これは私の問題の解決策のスポットでした。私の夢の解決策は、 "and.returnValue"呼び出しを変更することです。
ビルターナー

7
ジャスミンはこれを宣言するより良い方法を持つべきだと感じています。のようspyOn(fake, 'method').withArgs('abc').and.returnValue('Jane')spyOn(fake, 'method').withArgs('123').and.returnValue(98765)
jrharshath 2016年

@jrharshath .withArgsはjasmine 2.0では動作しません
hemkaran_raghav

1
.withArgsは実際には利用できません-テストを作成するときにそのような方法が理にかなっていることを意味しました。
jrharshath

9

$provideスパイの作成にも使用できます。パラメータ化されたデータを渡すand.returnValues代わりに使用してモックand.returnValue

Jasmine docsのとおり:でスパイをチェーンすることによりand.returnValues、関数へのすべての呼び出しは、戻り値リストの最後に到達するまで順番に特定の値を返します。

describe('my fn', () => {
    beforeEach(module($provide => {
        $provide.value('externalApi', jasmine.createSpyObj('externalApi', ['get']));
    }));

        it('get userName and Id', inject((externalApi) => {
            // Given
            externalApi.get.and.returnValues('abc','123');

            // When
            //insert your condition

            // Then
            // insert the expectation                
        }));
});

これは正解です。テストでは常にスパイがどのように呼び出されるかを正確に把握している必要があり、returnValues複数の呼び出しをサポートするためだけに使用する必要があります
Schmuli

2
単にakhouriの答えを明確にするために:このメソッドexternalApi.get.and.returnValues('abc','123')は、がit関数内で呼び出されたときにのみ 機能します。それ以外の場合、値のリストを設定すると、他の場所では、テストの実行順序が予測できないため、機能しません。実際、テストは、実行される順序に依存すべきではありません。
avi.elkharrat

0

私の場合、テストしているコンポーネントがあり、そのコンストラクターには、それぞれ異なる引数で2回呼び出されるgetAppConfigValueというメソッドを持つ構成サービスがあります。

constructor(private configSvc: ConfigService) {
  this.configSvc.getAppConfigValue('a_string');
  this.configSvc.getAppConfigValue('another_string');
}

私の仕様では、次のようにConfigServiceをTestBedに提供しました。

{
  provide: ConfigService,
  useValue: {
    getAppConfigValue: (key: any): any {
      if (key === 'a_string) {
        return 'a_value';
      } else if (key === 'another_string') {
        return 'another_value';
      }
    }
  } as ConfigService
}

そのため、getAppConfigValueのシグネチャが実際のConfigServiceで指定されているものと同じである限り、関数の内部での動作を変更できます。

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