2012-01-16 61 views
58

我們如何以編程方式清除茉莉花測試套件中的間諜?謝謝。我們如何在Jasmine中以編程方式清除間諜?

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 
}) 
+4

確定您選擇了正確的「正確」答案? – hgoebl 2015-02-10 08:12:46

+0

從Jasmine 2.0開始[「間諜只存在於其定義的describe或it塊中,並且在每個規範後都會被刪除。」](https://jasmine.github.io/2.0/ introduction.html#部分 - 間諜) – AJP 2017-05-24 21:10:23

回答

7

我不知道,如果它是一個好主意,但你可以簡單地設置在功能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'); 
    }) 

}) 

但也許它一個更好的主意來創建一個新的套件這種情況下,你需要從你的間諜的其他行爲。

+2

完美的安德烈亞斯。正是我需要的。如果你以後想弄清楚這是不是一個好主意。請告訴我。謝謝。 +1 – 2012-01-16 22:10:57

+0

這不是一個好主意,請參閱我的答案。 – FilmJ 2013-06-12 18:07:26

+0

@Andreas非常感謝!正是我所需要的... – zbynour 2014-03-13 06:47:34

36

我認爲這就是.reset()是:

spyOn($, 'ajax'); 

$.post('http://someUrl', someData); 

expect($.ajax).toHaveBeenCalled(); 

$.ajax.calls.reset() 

expect($.ajax).not.toHaveBeenCalled(); 
+8

因此,所有這些都會重置跟蹤狀態,如果您希望恢復默認行爲,這不會有所幫助。 – FilmJ 2013-06-12 17:21:21

+14

請注意,這已更改爲茉莉花2中的'mySpy.calls.reset()'。 – 2014-08-26 08:48:50

16

所以間諜的規範之間自動復位。

如果您在beforeEach()中使用andCallFake(),然後嘗試在規範內強制更改它(實際上可能是爲了防止您這麼做),您實際上沒有獲得原始功能的「恢復」權益, 。

所以要小心,特別是如果你的間諜被設置在全局對象,如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! 
+0

我試圖找出我需要做什麼來停止監視對象。你的回答非常明確和有幫助。茉莉花的岩石自動照顧它,拆卸下來。 – xverges 2013-10-15 05:27:21

94

設置isSpyfalse是一個非常糟糕的主意,因爲那麼你窺視一個間諜,當茉莉花在你規範結尾清除間諜,你不會得到原來的方法。 該方法將等於第一個間諜。

如果已經在監聽某個方法,並且您希望調用原始方法,則應調用andCallThrough()這將覆蓋第一個間諜行爲。

例如

var spyObj = spyOn(obj,'methodName').andReturn(true); 
spyObj.andCallThrough(); 

您可以通過調用this.removeAllSpies()this - SPEC)清除所有的間諜

+0

謝謝,這個作品! – dbrin 2014-06-17 17:51:53

+0

這是我最好的解決方案。 – 2014-08-12 09:40:35

+0

我寧願說設置isSpy爲false是一件壞事。我很喜歡安德烈亞斯K的思維。 – KSev 2014-09-22 20:22:22

8

在茉莉花2,間諜狀態在SpyStrategy情況下舉行。 你可以通過調用$.ajax.and來獲得這個實例。 見the Jasmine source code on GitHub

因此,設置不同的假的方法,這樣做:

$.ajax.and.callFake(function() { ... }); 

要恢復到原來的方法,這樣做:

$.ajax.and.callThrough(); 
+1

我不認爲'$ .ajax.and.andCallThrough();'是正確的。應該是'$ .ajax.and.callThrough();' – kriskodzi 2015-01-20 12:32:17

+0

這對我有效;在'beforeEach'裏面:'spyOn(Foobar,'getFoo')。和.returnValue('generic'); }然後在'it'裏面:'Foobar.getFoo.and.returnValue('special')'。謝謝! – 2017-04-28 12:50:31

0

或者你也可以做到這一點

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'); 
 
    }) 
 

 
})

在這種情況下,你使用相同的間諜,但只是改變它將返回的變種..

3

這對我在茉莉花2.5允許重新設置模擬阿賈克斯。

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);

相關問題