我们如何以编程方式清除茉莉花测试套件中的间谍?谢谢。
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
})
我们如何以编程方式清除茉莉花测试套件中的间谍?谢谢。
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
})
describe
或it
块中,并且在每次使用规格后都会被删除。”
Answers:
我不确定这是否是个好主意,但您可以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');
})
})
但是在这种情况下(如果您需要间谍的其他行为)创建一个新套件也许是一个更好的主意。
设置isSpy
到false
是一个非常糟糕的主意,因为那么你窥视一个间谍,当茉莉花在你规范结尾清除间谍,你不会得到原来的方法。该方法将等于第一个间谍。
如果已经在监视某个方法,而您想调用原始方法,则应该调用andCallThrough()
它将覆盖第一个间谍行为的方法。
例如
var spyObj = spyOn(obj,'methodName').andReturn(true);
spyObj.andCallThrough();
您可以通过调用this.removeAllSpies()
(this
-spec)清除所有间谍
spyOn(obj,'methodName').and.returnValue(true);
将间谍设置为返回值。然后,在进一步的测试中,您希望它监视像这样的真实功能:obj.methodName.and.callThrough();
我认为这就是.reset()的作用:
spyOn($, 'ajax');
$.post('http://someUrl', someData);
expect($.ajax).toHaveBeenCalled();
$.ajax.calls.reset()
expect($.ajax).not.toHaveBeenCalled();
mySpy.calls.reset()
在茉莉花2
mySpy.calls.reset()
重置间谍被调用时间的计数器。您可以通过expect(spy).toHaveBeenCalledTimes(1)
andCallFake
,而不是如何重置呼叫计数器。
因此,间谍会在规格之间自动重置。
如果andCallFake()
在a中使用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();
$.ajax.and.andCallThrough();
不正确。应该是$.ajax.and.callThrough();
beforeEach
:spyOn(Foobar, 'getFoo').and.returnValue('generic'); }
然后里面it
:Foobar.getFoo.and.returnValue('special')
。谢谢!
这在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);
从jasmine 2.5开始,您可以使用此全局设置来更新测试用例中的间谍:
jasmine.getEnv().allowRespy(true);
或者你可以做到
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');
})
})
在这种情况下,您使用相同的Spy,但只需更改它将返回的var。
我将发布此答案以解决OP @ Tri-Vuong的代码中的评论-这是我访问此页面的主要原因:
我想覆盖间谍...在这里做一些不同的事情
到目前为止,没有一个答案可以解决这一点,因此,我将发布我所学的知识并总结其他答案。
@Alissa正确调用它的时候,她解释了为什么这是一个坏主意,集isSpy
到false
-有效地刺探导致不再工作按计划茉莉的自动拆解行为间谍。她的解决方案(放在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()
。第一个测试说明了执行此操作的用例-我希望间谍在大多数测试中表现出一定的行为,然后在以后的一些测试中对其进行更改。
对于早期版本的茉莉花,改变相应的电话.andCallFake(
,.andCallThrough()
和.andReturnValue(
分别。
只需将spy方法设置为null
mockedService.spiedMethod = null;