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 heresinon.restore();});});// 然后是 Spiesvar 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; // truecallback2.methodA.restore() // 用原始方法替换间谍。仅当间谍替换了现有方法时可用。var isSourceAndTargetB = obj.methodA === callback2.methodA; // truevar isSourceAndTargetC = obj2.methodA === callback3.methodA; // falsevar isSourceAndTargetD = fn2 === obj2.methodA; // falseobj2.methodA.restore() // 可以通过调用恢复原始方法 object.method.restore() 恢复原始方法var isSourceAndTargetE = fn2 === obj2.methodA; // truevar isSourceAndTargetF = obj2.methodA === callback3.methodA; // falsevar isBool = spy.calledOnce; // falsespy(); // 如果他刚刚被执行了一次isBool = spy.calledOnce; // truespy("aaa");isBool = spy.calledTwice; // true 如果他刚刚被执行了两次返回trueisBool = spy.calledWith("aaa"); // true 如果曾经使用提供的参数调用过间谍,它将返回true。isBool = spy.calledWith("bbb"); // falsespy("bbb");isBool = spy.calledThrice; // true 如果他刚刚被执行了三次返回trueisBool = spy.calledWith("aaa"); // true 如果曾经使用提供的参数调用过间谍,它将返回true。isBool = spy.calledWith("bbb"); // truevar 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 从没有被执行过的话返回trueisBool = 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,否在返回falseisBool = spy.calledAfter(callback4); // false 是否在callback4之后被调用过,是返回true,否在返回falseisBool = spy.calledImmediatelyBefore(callback4); // true spy在callback4之前调用,并且没有在between spy and callback4被调用,符合条件返回true,否则返回falsespy();isBool = spy.calledImmediatelyBefore(callback4); // falseisBool = spy.calledImmediatelyAfter(callback4); // true spy在callback4之后调用,并且没有在between spy and callback4被调用,符合条件返回true,否则返回falsecallback4();isBool = spy.calledImmediatelyAfter(callback4); // falsedescribe("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
