https://sinonjs.org/releases/v7.5.0/spies/
spy 什么是测试间谍?
测试谍照是记录参数,返回值的值的函数 this,并抛出异常(如果有的话)的所有来电。间谍有两种类型:一些是匿名函数,而其他一些则包装被测系统中已经存在的方法。
var assert = require("assert");
var sinon = require("sinon");
var { fake, spy } = sinon;
debugger;
// 首先是一般设置
describe('My test suite', () => {
afterEach(() => {
// Restore the default sandbox here
sinon.restore();
});
});
// 然后是 Spies
var spy = sinon.spy(); // 使用spy创建匿名函数。间谍除了记录有关其通话(执行次数等)的信息外什么都不会做。
var obj = {
methodA: function () {
console.log(this.name);
}
};
var obj2 = {
methodA: function () {
console.log(this.name);
}
};
var fn2 = obj2.methodA;
var fn1 = function () { }
var callback2 = sinon.spy(obj); // 监视对象的所有方法。通常不建议这样做
var callback3 = sinon.spy(obj2, "methodA"); // 监听一个特定的函数
var callback4 = sinon.spy(fn1); // 监听一个特定的函数
var isSourceAndTargetA = obj.methodA === callback2.methodA; // true
callback2.methodA.restore() // 用原始方法替换间谍。仅当间谍替换了现有方法时可用。
var isSourceAndTargetB = obj.methodA === callback2.methodA; // true
var isSourceAndTargetC = obj2.methodA === callback3.methodA; // false
var isSourceAndTargetD = fn2 === obj2.methodA; // false
obj2.methodA.restore() // 可以通过调用恢复原始方法 object.method.restore() 恢复原始方法
var isSourceAndTargetE = fn2 === obj2.methodA; // true
var isSourceAndTargetF = obj2.methodA === callback3.methodA; // false
var isBool = spy.calledOnce; // false
spy(); // 如果他刚刚被执行了一次
isBool = spy.calledOnce; // true
spy("aaa");
isBool = spy.calledTwice; // true 如果他刚刚被执行了两次返回true
isBool = spy.calledWith("aaa"); // true 如果曾经使用提供的参数调用过间谍,它将返回true。
isBool = spy.calledWith("bbb"); // false
spy("bbb");
isBool = spy.calledThrice; // true 如果他刚刚被执行了三次返回true
isBool = spy.calledWith("aaa"); // true 如果曾经使用提供的参数调用过间谍,它将返回true。
isBool = spy.calledWith("bbb"); // true
var args = spy.args[0][0]; // 第一次调用的,第一个参数
args = spy.args[1][0]; // 第二次调用的,第一个参数
args = spy.args[2][0]; // 第三次调用的,第一个参数
var spyCall = spy.getCall(0); // spy.getCall(0); 返回第一次调用 当间谍被多次呼叫时,访问单个呼叫有助于进行更详细的行为验证。
spyCall = spy.getCall(1); // spy.getCall(1); 返回第二次调用
// 间谍对象是从返回的对象sinon.spy()。
// 当使用监视现有方法时sinon.spy(object, method),还可使用以下属性和方法object.method。
var count = spy.callCount; // 3 记录被执行次数
isBool = spy.called // true 至少被执行一次
isBool = spy.notCalled; // false 从没有被执行过的话返回true
isBool = spy.getCall(0) === spy.firstCall // false 虽然返回fasle 但是他也是获取第一次调用 第一次电话
isBool = spy.getCall(1) === spy.secondCall // 第二次通话 虽然返回fasle 但是他也是获取第二次调用
isBool = spy.getCall(2) === spy.thirdCall // 第三次通话 虽然返回fasle 但是他也是获取第三次调用
isBool = spy.getCall(2) === spy.lastCall // 最后一个电话 虽然返回fasle 但是他也是获取第三次调用
var spyCalls = spy.getCalls(); // 返回被调用次数组
callback4();
isBool = spy.calledBefore(callback4); // true 是否在callback4之前被调用过,如果调用过是返回tur,否在返回false
isBool = spy.calledAfter(callback4); // false 是否在callback4之后被调用过,是返回true,否在返回false
isBool = spy.calledImmediatelyBefore(callback4); // true spy在callback4之前调用,并且没有在between spy and callback4被调用,符合条件返回true,否则返回false
spy();
isBool = spy.calledImmediatelyBefore(callback4); // false
isBool = spy.calledImmediatelyAfter(callback4); // true spy在callback4之后调用,并且没有在between spy and callback4被调用,符合条件返回true,否则返回false
callback4();
isBool = spy.calledImmediatelyAfter(callback4); // false
describe("xxxx", function () {
var object = { method: function () { } };
var spy1 = sinon.spy(object, "method");
object.method(42);
object.method(1);
// spy.withArgs(arg1[, arg2, ...]); 创建一个间谍,仅在接收到的参数与传递给的参数匹配时记录
assert(spy1.withArgs(42).calledOnce); // 通过
assert(spy1.withArgs(1).calledOnce); // 通过
})
// this对象数组,spy.thisValues[0]是this第一个调用的对象。
var self = spy.thisValues // [undefined,undefined,undefined,undefined]
var obj = {};
spy.apply(obj, []);
self = spy.thisValues // [undefined,undefined,undefined,undefined, obj]
var values = spy.returnValues; // 调用函数的返回值数组
var ex = spy.exceptions; // 异常 引发的异常对象数组spy.exceptions[0]是第一次调用引发的异常。如果呼叫没有引发错误,则呼叫位置中的值.exceptions将为undefined。
spy.threw(); // true如果间谍至少引发一次异常,则返回。
spy.threw("TypeError"); // true如果spy至少抛出一次所提供类型的异常,则返回。
spy.threw(obj); // 返回:true如果间谍至少一次抛出了提供的异常对象。
spy.alwaysThrew(); // true如果间谍总是抛出异常,则返回。
spy.alwaysThrew("TypeError"); // true如果spy总是抛出所提供类型的异常,则返回。
spy.alwaysThrew(obj); // 返回:true如果间谍总是抛出所提供的异常对象。
spy.returned(obj); // 返回true如果间谍返回至少提供一次价值。
// 对对象和数组使用深度比较。用spy.returned(sinon.match.same(obj))严格的比较(见的匹配)。
spy.alwaysReturned(obj); // 返回true如果间谍总是返回所提供的价值。
// 验证this的
spy.calledOn(obj); // 返回true是否使用obj 至少调用过一次间谍this。calledOn也接受匹配器spyCall.calledOn(sinon.match(fn))(请参阅matchers)。
spy.alwaysCalledOn(obj); // 返回true是否始终以objas 调用间谍this。
spy.calledOnceWith(/*arg1, arg2, ...*/); // 返回true是否总共总共只对spy调用一次,并且一次调用使用的是提供的参数。
spy.alwaysCalledWith(/*arg1, arg2, ...*/); // 返回true是否始终使用提供的参数(可能还有其他参数)调用spy。
spy.calledWithExactly(/*arg1, arg2, ...*/); // 返回true是否使用提供的参数调用了间谍至少一次,没有其他调用。
spy.calledOnceWithExactly(/*arg1, arg2, ...*/); // 返回true是否总共总共只对spy调用一次,并且一次调用使用的是提供的确切参数,而没有其他调用。
spy.alwaysCalledWithExactly(/*arg1, arg2, ...*/); // 返回true是否始终使用提供的确切参数调用spy。
spy.calledWithMatch(/*arg1, arg2, ...*/); // 回true是否使用匹配的参数(可能还有其他参数)调用了间谍。行为与相同spy.calledWith(sinon.match(arg1), sinon.match(arg2), ...)。
spy.alwaysCalledWithMatch(/*arg1, arg2, ...*/); // 返回true是否始终使用匹配的参数(可能还有其他参数)调用spy。行为与相同spy.alwaysCalledWith(sinon.match(arg1), sinon.match(arg2), ...)。
spy.neverCalledWith(/*arg1, arg2, ...*/); // 返回true是否从未使用提供的参数调用间谍/存根。
spy.neverCalledWithMatch(/*arg1, arg2, ...*/); // 返回true是否从未使用匹配的参数调用间谍/存根。行为与相同spy.neverCalledWith(sinon.match(arg1), sinon.match(arg2), ...)。
spy.calledWithNew(); // 返回true是否将spy / stub称为new运算符。请注意,这是根据this对象的值和spy函数的推断的prototype,因此,如果您主动返回正确的对象类型,则可能会产生误报。
/*
spy.printf("format string", [arg1, arg2, ...]);
返回传递的格式字符串,并执行以下替换:
%n
间谍的名称“间谍”(默认情况下)
%c
间谍被调用的次数,以单词(“一次”,“两次”等)表示
%C
间谍程序调用的字符串表示形式的列表,每个调用以换行符和四个空格为前缀
%t
以逗号分隔的this值列表,调用间谍
%n
传递给的第n个参数的格式值printf
%*
传递给(非格式字符串)参数的逗号分隔列表 printf
%D
由所有对间谍的调用接收到的参数的多行列表
*/
var str = spy.printf("format string: %c | %n", [spy.callCount, spy.name]);
spy.resetHistory(); // 重置间谍的状态
isBool = spy.called; // false