我对我所看到的行为感到困惑。我的间谍一直在误报这些争论。如果我使用相同的签名和参数创建相同的函数并分别监视它,那么副本工作正常。我无法弄清楚发生了什么!
所以,这是代码:
注意:alert
是原始函数,test
是我创建的新函数,用于检查正在发生的事情。
# index.js
class Alerter {
getOnErrorFn(name) {
return (error) => {
...
alert = {
opts: {
tags: 'Unknown Error'
}
}
...
if (alert) {
this.test(name, error.message, Object.assign({}, alert.opts, {smc_error: error.toLog()}), alert.level);
this.alert(name, error.message, Object.assign({}, alert.opts, {smc_error: error.toLog()}), alert.level); }
};
}
test(serviceName, message, opts={}, level=this.CRITICAL) {
console.log(serviceName, message, opts, level);
}
alert(serviceName, message, opts={}, level=this.CRITICAL) {
console.log(serviceName, message, opts, level);
...
}
这是我的测试代码(所有其他测试都已注释掉,这是测试套件中唯一的文件);
# alerter.spec.js
const sandbox = sinon.sandbox.create();
describe('Alerter', function(){
let alerter;
let name = 'test-service';
let message = 'test message';
beforeEach(() => {
alerter = new Alerter(name);
});
afterEach(() => {
sandbox.restore();
});
describe('getOnErrorFn()', () => {
it.only('handles non-SMCError errors and assumes they should be alerted', () => {
const spy = sandbox.spy(alerter, 'test');
const spi = sandbox.spy(alerter, 'alert');
const onError = alerter.getOnErrorFn(name);
const error = new Error();
const smcError = SMCError.from(error);
onError(error);
expect(spy).to.have.been.calledWith(name, smcError.message, {smc_error: smcError.toLog(), tags: 'Unknown Error'}, undefined);
expect(spi).to.have.been.calledWith(name, smcError.message, {smc_error: smcError.toLog(), tags: 'Unknown Error'}, undefined);
});
});
});
这是测试运行的结果....这是我的绝对坚果!
$ npm test
> smc-alerting@2.1.3 test /Users/al/Studio/Projects/smc/app/smc-alerting
> mocha test/**/*.spec.js
Alerter
getOnErrorFn()
TEST test-service Caught Error { tags: 'Unknown Error',
smc_error: 'Error Caught Error\n caused by: Caught Error' } critical
ALERT test-service Caught Error { tags: 'Unknown Error',
smc_error: 'Error Caught Error\n caused by: Caught Error' } critical
1) handles non-SMCError errors and assumes they should be alerted
0 passing (34ms)
1 failing
1) Alerter getOnErrorFn() handles non-SMCError errors and assumes they should be alerted:
expected alert to have been called with arguments test-service, Caught Error, {
smc_error: "Error Caught Error
caused by: Caught Error",
tags: "Unknown Error"
}, undefined
alert(test-service, Caught Error, { smc_error: "Error Caught Error
caused by: Caught Error" }, undefined) at /Users/al/Studio/Projects/smc/app/smc-alerting/src/index.js:46:14
AssertionError: expected alert to have been called with arguments test-service, Caught Error, {
smc_error: "Error Caught Error
caused by: Caught Error",
tags: "Unknown Error"
}, undefined
alert(test-service, Caught Error, { smc_error: "Error Caught Error
caused by: Caught Error" }, undefined) at src/index.js:46:14
at Context.it.only (test/index.spec.js:173:32)
npm ERR! Test failed. See above for more details.
因此,请注意,两个console.log
语句都会打印相同的结果。但是,alert
函数的间谍失败,打印输出表明函数是在第三个参数中缺少tags
属性的情况下调用的。 WTF!
或者有什么我不知道在这里发生的事情吗?
所有人都非常感谢。提前谢谢!
答案 0 :(得分:0)
Darnit。得到了答案。长话短说:使用不可变对象!
alert()
在代码后面有delete opts.tags
行,这当然会在sinon到处检查时改变原始对象。