我们如何在Jasmine中以编程方式清除间谍?

我们如何以编程方式清除茉莉花testing套件中的间谍? 谢谢。

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(ab()).toEqual('spy1'); }) it('should return spy2', function() { abisSpy = false; spyOn(a, 'b').andCallFake(function(params) { return 'spy2'; }) expect(ab()).toEqual('spy2'); }) }) 

但是,也许这是一个更好的主意,为这种情况下,你需要从你的间谍其他行为创build一个新的套件。

设置isSpyfalse是一个非常糟糕的主意,从那时起,你就会监视一个间谍,当茉莉花在你的规范结束时清除了间谍,你将不会得到原来的方法。 该方法将等于第一个间谍。

如果已经在andCallThrough()某个方法,并且想要调用原始方法,则应该调用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() ,然后试图在spec中强制改变它,你实际上并没有从原始函数的“恢复”中获得好处(这可能是为什么它试图阻止你这么做) 。

所以要小心,特别是如果你的间谍被设置在一个全球性的对象,如jQuery。

示范:

 var a = {b:function() { return 'default'; } }; // global scope (ie jQuery) var originalValue = ab; describe("SpyOn test", function(){ it('should return spy1', function(){ spyOn(a, 'b').andCallFake(function(params) { return 'spy1'; }) expect(ab()).toEqual('spy1'); }); it('should return default because removeAllSpies() happens in teardown', function(){ expect(ab()).toEqual('default'); }); it('will change internal state by "forcing" a spy to be set twice, overwriting the originalValue', function(){ expect(ab()).toEqual('default'); spyOn(a, 'b').andCallFake(function(params) { return 'spy2'; }) expect(ab()).toEqual('spy2'); // This forces the overwrite of the internal state abisSpy = false; spyOn(a, 'b').andCallFake(function(params) { return 'spy3'; }) expect(ab()).toEqual('spy3'); }); it('should return default but will not', function(){ expect(ab()).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(ab()).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. abisSpy = false; spyOn(a, 'b').andCallFake(function(params) { return 'spy2'; }) expect(ab()).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(ab()).toEqual('spy1'); }); }); // If you were hoping jasmine would cleanup your mess even after the spec is completed... console.log(ab == 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中为我工作,以允许重新设置模拟阿贾克斯。

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