How do we clear spy programmatically in Jasmine?

后端 未结 10 2278
孤独总比滥情好
孤独总比滥情好 2020-12-15 02:11

How do we clear the spy in a jasmine test suite programmatically? Thanks.

beforeEach(function() {
  spyOn($, \"ajax\").andCallFake(function(params){
  })
})
         


        
相关标签:
10条回答
  • 2020-12-15 02:59

    setting isSpy to false is a very bad idea, since then you spy on a spy and when Jasmine clears the spies at the end of your spec you won't get the original method. the method will be equal to the first spy.

    if are already spying on a method and you want the original method to be called instead you should call andCallThrough() which will override the first spy behavior.

    for example

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

    you can clear all spies by calling this.removeAllSpies() (this - spec)

    0 讨论(0)
  • 2020-12-15 03:04

    So spies are reset automatically between specs.

    You actually do not get the benefit of "restoration" of the original function if you use andCallFake() within a beforeEach() and then attempt to forcibly change it within a spec (which is likely why it tries to prevent you from doing so).

    So be careful, especially if your spy is being set on a global object such as jQuery.

    Demonstration:

    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 讨论(0)
  • 2020-12-15 03:09

    This worked for me in Jasmine 2.5 to allow re-setting of mock 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();
        });
    }
    

    Then you can call it multiple times without error. spyOnAjax(mock1); spyOnAjax(mock2);

    0 讨论(0)
  • 2020-12-15 03:09

    just set the spy method to null

    mockedService.spiedMethod = null;
    
    0 讨论(0)
提交回复
热议问题