簡體   English   中英

我們如何在Jasmine中以編程方式清除間諜?

[英]How do we clear spy programmatically in 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
})

isSpy設置為false是一個非常糟糕的主意,因為從那時起您就可以監視間諜,而當Jasmine在規范結束時清除間諜時,您將無法獲得原始方法。 該方法將等於第一個間諜。

如果已經在監視某個方法,而您想調用原始方法,則應該調用andCallThrough() ,它將覆蓋第一個間諜行為。

例如

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

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

我認為這就是.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);

我不確定這是否是一個好主意,但您可以將函數上的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');
    })

})

但是在這種情況下(如果您需要間諜的其他行為)創建一個新的套件可能是一個更好的主意。

或者你可以做到

 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(ab()).toEqual('spy1'); }) it('should return spy2', function() { c = 'spy2'; expect(ab()).toEqual('spy2'); }) }) 

在這種情況下,您使用相同的Spy,但只需更改它將返回的var。

我將發布此答案以解決@ Tri-Vuong OP代碼中的評論-這是我訪問此頁面的主要原因:

我想覆蓋間諜...在這里做一些不同的事情

到目前為止,沒有一個答案可以解決這一點,因此,我將發布所學內容並總結其他答案。

@Alissa解釋了將isSpy設置為false不好的主意時正確地調用了它-有效地監視了間諜,從而導致Jasmine的自動拆解行為不再起作用。 她的解決方案(放在OP上下文中,並針對Jasmine 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() 第一個測試說明了執行此操作的用例-我希望間諜在大多數測試中表現出一定的行為,然后在以后的一些測試中對其進行更改。

對於早期版本的Jasmine,請將相應的調用分別更改為.andCallFake( ,. .andCallThrough().andReturnValue(

從jasmine 2.5開始,您可以使用此全局設置來更新測試用例中的間諜:

jasmine.getEnv().allowRespy(true);

只需將spy方法設置為null

mockedService.spiedMethod = null;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM