Как мы можем очистить шпиона программно в Жасмин?
как мы очищаем шпиона в наборе тестов 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
})
8 ответов:
Я не уверен, что это хорошая идея, но вы можете просто установить
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'); }) })но, возможно, его лучшая идея, чтобы создать новый набор для этого случая, когда вам нужно другое поведение от вашего шпиона.
задание
isSpytofalseэто очень плохая идея, так как тогда вы шпионите за шпионом, и когда Жасмин очищает шпионов в конце вашей спецификации, вы не получите оригинальный метод. метод будет равен первому шпиону.если вы уже шпионили за методом, и вы хотите, чтобы исходный метод был вызван вместо этого вы должны вызвать
andCallThrough()который будет переопределять первое поведение шпиона.var spyObj = spyOn(obj,'methodName').andReturn(true); spyObj.andCallThrough();вы можете очистить всех шпионов, позвонив
this.removeAllSpies()(this- spec)
Я думаю, что это .сброс() для:
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 состояние spy хранится в экземпляре SpyStrategy. Вы можете получить доступ к этому экземпляру вызова
$.ajax.and. Смотрите исходный код жасмина на GitHub.Итак, чтобы установить другой поддельный метод, сделайте это:
$.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);
или вы можете сделать это
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'); }) })в этом случае вы используете тот же шпион, но просто измените var, который он вернет..