sinon.getCall(0).args[0] 返回函数的结果,而不是第一个 arg
sinon.getCall(0).args[0] is returning the result of the function, not first arg
我正在使用 AVA 和 Sinon 测试一个小功能。函数看起来基本上像这样(为简洁起见进行了编辑):
mergeDefaults: function (opts) {
**console.log('log 1 ->', opts);**
opts = _.defaultsDeep(opts, defaultOptions);
return opts;
}
我已经编写了一个测试来确保将正确的参数传递给 _.defaultsDeep
。
test.before(t => {
sandbox = sinon.sandbox.create();
defaultsDeepSpy = sandbox.spy(_, 'defaultsDeep');
mergeDefaults(Object.assign({}, testOptions));
});
test('mergeDefaults runs _.defaultsDeep with the correct parameters', t => {
**console.log('log 2 ->', defaultsDeepSpy.getCall(0).args[0]);**
t.is(defaultsDeepSpy.getCall(0).args[0], testOptions);
t.is(defaultsDeepSpy.getCall(0).args[1], defaultOptions);
});
test.after.always(t => {
sandbox.restore();
});
我 运行 遇到的问题是日志 1 和日志 2 不一样。据我了解,
spy.getCall(n).args[m]
returns 第 m 个参数从第 n 次调用该函数时传递给该函数。但是,在这种情况下,log 2 实际上返回的是函数的结果,而不是第一个参数。
选项对象看起来像这样:
testOptions = {
key1: 11,
key2: 22,
key3: 33
}
defaultOptions = {
key1: 1,
key2: 2,
key3: 3,
key4: 4,
key5: 5
}
但是 console.logs 看起来像这样:
log 1 -> testOptions = {
key1: 11,
key2: 22,
key3: 33
}
log 2 -> testOptions = {
key1: 11,
key2: 22,
key3: 33,
key4: 4,
key5: 5
}
因此 spy.getCall(0).args[0]
a.k.a“log 2”实际上返回了 _.defaultsDeep
运行后“opts”的内容。我做错了什么?
您遇到的根本问题是对参数的引用(在本例中为 opts
)是您使用值操作的同一对象(因为所有对象都是通过引用传递的 JavaScript).实际上,您正在更改 opts
指向的物理位置。
由于 Sinon 不接受您传入的对象的 "snapshot" 或 "copy"(它只是 returns 您传入的相同对象引用),你也影响了 Sinon 返回的内容。
要解决这个问题,代码应该类似于
mergeDefaults: function (opts) {
return _.defaultsDeep(Object.assign({}, opts), defaultOptions);
}
Object.assign
将创建一个新对象(以及内存中的关联位置)。因此,它将 opts
保持不变,因此您可以检查传入的内容。
我正在使用 AVA 和 Sinon 测试一个小功能。函数看起来基本上像这样(为简洁起见进行了编辑):
mergeDefaults: function (opts) {
**console.log('log 1 ->', opts);**
opts = _.defaultsDeep(opts, defaultOptions);
return opts;
}
我已经编写了一个测试来确保将正确的参数传递给 _.defaultsDeep
。
test.before(t => {
sandbox = sinon.sandbox.create();
defaultsDeepSpy = sandbox.spy(_, 'defaultsDeep');
mergeDefaults(Object.assign({}, testOptions));
});
test('mergeDefaults runs _.defaultsDeep with the correct parameters', t => {
**console.log('log 2 ->', defaultsDeepSpy.getCall(0).args[0]);**
t.is(defaultsDeepSpy.getCall(0).args[0], testOptions);
t.is(defaultsDeepSpy.getCall(0).args[1], defaultOptions);
});
test.after.always(t => {
sandbox.restore();
});
我 运行 遇到的问题是日志 1 和日志 2 不一样。据我了解,
spy.getCall(n).args[m]
returns 第 m 个参数从第 n 次调用该函数时传递给该函数。但是,在这种情况下,log 2 实际上返回的是函数的结果,而不是第一个参数。
选项对象看起来像这样:
testOptions = {
key1: 11,
key2: 22,
key3: 33
}
defaultOptions = {
key1: 1,
key2: 2,
key3: 3,
key4: 4,
key5: 5
}
但是 console.logs 看起来像这样:
log 1 -> testOptions = {
key1: 11,
key2: 22,
key3: 33
}
log 2 -> testOptions = {
key1: 11,
key2: 22,
key3: 33,
key4: 4,
key5: 5
}
因此 spy.getCall(0).args[0]
a.k.a“log 2”实际上返回了 _.defaultsDeep
运行后“opts”的内容。我做错了什么?
您遇到的根本问题是对参数的引用(在本例中为 opts
)是您使用值操作的同一对象(因为所有对象都是通过引用传递的 JavaScript).实际上,您正在更改 opts
指向的物理位置。
由于 Sinon 不接受您传入的对象的 "snapshot" 或 "copy"(它只是 returns 您传入的相同对象引用),你也影响了 Sinon 返回的内容。
要解决这个问题,代码应该类似于
mergeDefaults: function (opts) {
return _.defaultsDeep(Object.assign({}, opts), defaultOptions);
}
Object.assign
将创建一个新对象(以及内存中的关联位置)。因此,它将 opts
保持不变,因此您可以检查传入的内容。