[英]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.