How do we clear spy programmatically in Jasmine?

2020-02-24 04:47发布

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

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

10条回答
2楼-- · 2020-02-24 05:35

I'm posting this answer to address the comment in OP @Tri-Vuong's code - which was my main reason for my visiting this page:

I want to override the spy ... here and do it a little differently

None of the answers so far address this point, so I'll post what I've learned and summarize the other answers as well.

@Alissa called it correctly when she explained why it is a bad idea to set isSpy to false - effectively spying on a spy resulting in the auto-teardown behavior of Jasmine no longer functioning as intended. Her solution (placed within the OP context and updated for Jasmine 2+) was as follows:

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

The last it test demonstrates how one could change the behavior of an existing spy to something else besides original behavior: "and-declare" the new behavior on the spyObj previously stored in the variable in the beforeEach(). The first test illustrates my use case for doing this - I wanted a spy to behave a certain way for most of the tests, but then change it for a few tests later.

For earlier versions of Jasmine, change the appropriate calls to .andCallFake(, .andCallThrough(), and .andReturnValue( respectively.

查看更多
再贱就再见
3楼-- · 2020-02-24 05:37

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)

查看更多
▲ chillily
4楼-- · 2020-02-24 05:41

Or you can do it

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

})

In this case you use the same Spy but just change the var that it will return..

查看更多
成全新的幸福
5楼-- · 2020-02-24 05:43

In Jasmine 2, the spy state is held in a SpyStrategy instance. You can get hold of this instance calling $.ajax.and. See the Jasmine source code on GitHub.

So, to set a different fake method, do this:

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

To reset to the original method, do this:

$.ajax.and.callThrough();
查看更多
登录 后发表回答