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的所有跟蹤