ジャスミンでプログラムでスパイをどのようにクリアするのでしょうか?
-
29-10-2019 - |
質問
ジャスミンテストスイートのスパイをプログラムでクリアするにはどうすればよいですか?ありがとう。
beforeEach(function() {
spyOn($, "ajax").andCallFake(function(params){
})
})
it("should do something", function() {
//I want to override the spy on ajax here and do it a little differently
})
解決
それが良いアイデアかどうかはわかりませんが、あなたは単に設定することができます isSpy
falseの関数のフラグ:
describe('test', function() {
var a = {b: function() {
}};
beforeEach(function() {
spyOn(a, 'b').andCallFake(function(params) {
return 'spy1';
})
})
it('should return spy1', function() {
expect(a.b()).toEqual('spy1');
})
it('should return spy2', function() {
a.b.isSpy = false;
spyOn(a, 'b').andCallFake(function(params) {
return 'spy2';
})
expect(a.b()).toEqual('spy2');
})
})
しかし、スパイから他の動作が必要なこのケースのために新しいスイートを作成するのはもっと良いアイデアかもしれません。
他のヒント
設定 isSpy
に false
それ以来、非常に悪い考えです。それ以来、スパイをスパイし、ジャスミンが仕様の端でスパイをクリアすると、元の方法が得られません。この方法は、最初のスパイに等しくなります。
すでにメソッドをスパイしていて、代わりに元の方法を呼び出す必要がある場合は、電話する必要があります andCallThrough()
最初のスパイ動作をオーバーライドします。
例えば
var spyObj = spyOn(obj,'methodName').andReturn(true);
spyObj.andCallThrough();
呼び出してすべてのスパイをクリアできます this.removeAllSpies()
(this
- 仕様)
それが何だと思います .reset() のためです:
spyOn($, 'ajax');
$.post('http://someUrl', someData);
expect($.ajax).toHaveBeenCalled();
$.ajax.calls.reset()
expect($.ajax).not.toHaveBeenCalled();
そのため、スパイは仕様間で自動的にリセットされます。
実際には、使用している場合、元の関数の「修復」のメリットが得られません andCallFake()
以内 beforeEach()
そして、仕様内で強制的に変更しようとします(これが、そうすることを防止しようとする理由です)。
特に、スパイがjQueryなどのグローバルオブジェクトに設定されている場合は注意してください。
デモンストレーション:
var a = {b:function() { return 'default'; } }; // global scope (i.e. jQuery)
var originalValue = a.b;
describe("SpyOn test", function(){
it('should return spy1', function(){
spyOn(a, 'b').andCallFake(function(params) {
return 'spy1';
})
expect(a.b()).toEqual('spy1');
});
it('should return default because removeAllSpies() happens in teardown', function(){
expect(a.b()).toEqual('default');
});
it('will change internal state by "forcing" a spy to be set twice, overwriting the originalValue', function(){
expect(a.b()).toEqual('default');
spyOn(a, 'b').andCallFake(function(params) {
return 'spy2';
})
expect(a.b()).toEqual('spy2');
// This forces the overwrite of the internal state
a.b.isSpy = false;
spyOn(a, 'b').andCallFake(function(params) {
return 'spy3';
})
expect(a.b()).toEqual('spy3');
});
it('should return default but will not', function(){
expect(a.b()).toEqual('default'); // FAIL
// What's happening internally?
expect(this.spies_.length).toBe(1);
expect(this.spies_[0].originalValue).toBe(originalValue); // FAIL
});
});
describe("SpyOn with beforeEach test", function(){
beforeEach(function(){
spyOn(a, 'b').andCallFake(function(params) {
return 'spy1';
})
})
it('should return spy1', function(){
// inspect the internal tracking of spies:
expect(this.spies_.length).toBe(1);
expect(this.spies_[0].originalValue).toBe(originalValue);
expect(a.b()).toEqual('spy1');
});
it('should return spy2 when forced', function(){
// inspect the internal tracking of spies:
expect(this.spies_.length).toBe(1);
expect(this.spies_[0].originalValue).toBe(originalValue);
// THIS EFFECTIVELY changes the "originalState" from what it was before the beforeEach to what it is now.
a.b.isSpy = false;
spyOn(a, 'b').andCallFake(function(params) {
return 'spy2';
})
expect(a.b()).toEqual('spy2');
});
it('should again return spy1 - but we have overwritten the original state, and can never return to it', function(){
// inspect the internal tracking of spies:
expect(this.spies_.length).toBe(1);
expect(this.spies_[0].originalValue).toBe(originalValue); // FAILS!
expect(a.b()).toEqual('spy1');
});
});
// If you were hoping jasmine would cleanup your mess even after the spec is completed...
console.log(a.b == originalValue) // FALSE as you've already altered the global object!
Jasmine 2では、スパイ状態はSpystrategyインスタンスに保持されています。このインスタンスの呼び出しを手に入れることができます $.ajax.and
。見る GithubのJasmineソースコード.
したがって、別の偽の方法を設定するには、これを行います。
$.ajax.and.callFake(function() { ... });
元の方法にリセットするには、これを行います。
$.ajax.and.callThrough();
これは、Jasmine 2.5で私のために機能し、模擬Ajaxの再設定を可能にしました。
function spyOnAjax(mockResult) {
// must set to true to allow multiple calls to spyOn:
jasmine.getEnv().allowRespy(true);
spyOn($, 'ajax').and.callFake(function () {
var deferred = $.Deferred();
deferred.resolve(mockResult);
return deferred.promise();
});
}
その後、エラーなしで複数回呼び出すことができます。 spyonajax(mock1); spyonajax(mock2);
またはあなたはそれをすることができます
describe('test', function() {
var a, c;
c = 'spy1';
a = {
b: function(){}
};
beforeEach(function() {
spyOn(a, 'b').and.callFake(function () {
return c;
});
})
it('should return spy1', function() {
expect(a.b()).toEqual('spy1');
})
it('should return spy2', function() {
c = 'spy2';
expect(a.b()).toEqual('spy2');
})
})
この場合、あなたは同じスパイを使用しますが、それが返すVARを変更するだけです。
OP @Tri -Vuongのコードにコメントに対処するためにこの回答を投稿しています。これが私がこのページを訪問した私の主な理由でした。
スパイをオーバーライドしたい...ここで少し違ったやり方でやりたい
これまでの答えはどれもこの点に対処していないので、私が学んだことを投稿し、他の答えも要約します。
@Alissaは、彼女が設定するのが悪い考えである理由を説明したときにそれを正しく呼びました isSpy
に false
- スパイを効果的にスパイすると、意図したとおりに機能しなくなったジャスミンの自動テアダウン挙動が生じます。彼女の解決策(OPコンテキスト内に配置され、ジャスミン2+のために更新された)は次のとおりでした。
beforeEach(() => {
var spyObj = spyOn(obj,'methodName').and.callFake(function(params){
}) // @Alissa's solution part a - store the spy in a variable
})
it("should do the declared spy behavior", () => {
// Act and assert as desired
})
it("should do what it used to do", () => {
spyObj.and.callThrough(); // @Alissa's solution part b - restore spy behavior to original function behavior
// Act and assert as desired
})
it("should do something a little differently", () => {
spyObj.and.returnValue('NewValue'); // added solution to change spy behavior
// Act and assert as desired
})
最後 it
テストでは、既存のスパイの動作を元の行動以外の何かに変える方法を示しています。」and
-declare "以前に変数に保存されていたspyobjの新しい動作 beforeEach()
. 。最初のテストでは、これを行うための私のユースケースを示しています - 私はスパイがほとんどのテストで特定の方法で動作するようにしたかったのですが、後でいくつかのテストでそれを変更しました。
ジャスミンの以前のバージョンの場合、適切な呼び出しを変更します .andCallFake(
, .andCallThrough()
, 、 と .andReturnValue(
それぞれ。
Jasmine 2.5から、このグローバルな設定を使用して、テストケース内のスパイを更新できます。
jasmine.getEnv().allowRespy(true);
スパイメソッドをnullに設定するだけです
mockedService.spiedMethod = null;