Spy用来追踪函数的调用历史信息(是否被调用、调用参数列表、被请求次数等)。Spy仅存在于定义它的describe和it方法块中,并且每次在spec执行完之后被销毁。
当在一个对象上使用spyOn方法后即可模拟调用对象上的函数,此时对所有函数的调用是不会执行实际代码的。
两个Spy常用的expect:
- toHaveBeenCalled: 函数是否被调用
- toHaveBeenCalledWith: 调用函数时的参数
describe("A spy", function() {
var foo, bar = null;
beforeEach(function() {
foo = {
setBar: function(value) {
bar = value;
}
};
spyOn(foo, "setBar"); // 在foo对象上添加spy
// 此时调用foo对象上的方法,均为模拟调用,因此不会执行实际的代码
foo.setBar(123); // 调用foo的setBar方法
foo.setBar(456, "another param");
});
it("tracks that the spy was called", function() {
expect(foo.setBar).toHaveBeenCalled(); //判断foo的setBar是否被调用
});
it("tracks all the arguments of its calls", function() {
expect(foo.setBar).toHaveBeenCalledWith(123); //判断被调用时的参数
expect(foo.setBar).toHaveBeenCalledWith(456, "another param");
});
it("stops all execution on a function", function() {
expect(bar).toBeNull(); // 由于是模拟调用,因此bar值并没有改变
});
});
常用跟踪属性
除了上面提到的最常用的两种,还有以下
- spy链式调用and.callThrough 后,在获取spy的同时,调用实际的函数。
- spy链式调用and.returnValue ,返回指定值。
- spy链式调用and.callFake ,执行指定函数。
- spy链式调用and.throwError ,抛出异常。
- spy恢复到原始状态,不执行任何操作。
- 当没有函数可以spy的时候,可以创建一个“基础的”spy,它的背后没有任何实际的操作
- 使用jasmine.createSpyObj 可以模拟多个spies。给jasmine.createSpyObj 传入一个字符串数组,返回一个对象,字符串数组的每一项都是它的spy类型的属性。
其他跟踪属性
spy的任何调用都可以使用calls 属性跟踪
.calls.any()
如果spy没有被调用过,则返回false,否则返回true.calls.count()
返回spy被调用的次数.calls.argsFor(index)
返回spy被第index次调用时的参数.calls.allArgs()
返回spy所有被调用的参数.calls.all()
返回spy所有被调用的this 上下文和参数.calls.mostRecent()
返回spy最近一次被调用的this 上下文和参数.calls.first()
返回spy第一次被调用的this 上下文和参数.calls.reset()
清空spy的所有跟踪