我有以下js用于对错误处理程序进行单元测试:
import assert from 'assert';
import deepClone from 'lodash.clonedeep';
import deepEqual from 'lodash.isequal';
import { spy } from 'sinon';
import errorHandler from './index';
function getValidError(constructor = SyntaxError) {
let error = new constructor();
error.status = 400;
error.body = {};
error.type = 'entity.parse.failed';
return error;
}
describe('errorHandler', function() {
let err;
let req;
let res;
let next;
let clonedRes;
describe('When the error is not an instance of SyntaxError', function() {
err = getValidError(Error);
req = {};
res = {};
next = spy();
clonedRes = deepClone(res);
errorHandler(err, req, res, next);
it('should not modify res', function() {
assert(deepEqual(res, clonedRes));
});
it('should call next()', function() {
assert(next.calledOnce);
});
});
...(#other test cases all similar to the first)
describe('When the error is a SyntaxError, with a 400 status, has a `body` property set, and has type `entity.parse.failed`', function() {
err = getValidError();
req = {};
let res = {
status: spy(),
set: spy(),
json: spy()
};
let next = spy();
errorHandler(err, req, res, next);
it('should set res with a 400 status code', function() {
assert(res.status.calledOnce);
assert(res.status.calledWithExactly(400));
});
it('should set res with an application/json content-type header', function() {
assert(res.set.calledOnce);
assert(res.set.calledWithExactly('Content-Type', 'application/json'));
});
it('should set res.json with error code', function() {
assert(res.json.calledOnce);
assert(res.json.calledWithExactly({ message: 'Payload should be in JSON format' }));
});
});
});
请注意,我在describe块中的let
,res
和next
前面有clonedRes
,当“错误是语法错误...”时。< / p>
在没有let
的情况下,我的测试失败。我不明白为什么我需要为此再次添加let
,而不是在同一块中为err
和req
添加。有人可以帮我解释一下吗?
答案 0 :(得分:2)
在严格模式下(通常在良好的线性代码中),必须先将变量声明给变量。另外,const
和let
变量必须在一个块中一次声明,并且不能再声明。重新声明已经声明的err
(或任何其他变量)将引发错误,这就是为什么您应该仅在let <varname>
函数中看到describe('errorHandler'
一次的原因:
const describe = cb => cb();
let something;
describe(() => {
something = 'foo';
});
let something;
describe(() => {
something = 'bar';
});
另外describe
个在 describe('errorHandler'
中的对象已经访问了err
。
根本不声明变量,以草率模式对其进行分配将导致将其分配给全局对象,这几乎总是不希望的,can introduce bugs and errors。例如:
// Accidentally implicitly referencing window.status, which can only be a string:
status = false;
if (status) {
console.log('status is actually truthy!');
}
也就是说,将变量的作用域保持在尽可能狭窄的范围内通常是一个好主意-仅在需要外部范围中的值时才分配给外部变量。考虑仅在分配给它们的describe
内部声明变量,这还有一个额外的好处,即允许您使用const
而不是let
:
describe('When the error is not an instance of SyntaxError', function() {
const err = getValidError(Error);
const req = {};
const res = {};
const next = spy();
const clonedRes = deepClone(res);
errorHandler(err, req, res, next);
// etc
});
// etc
describe('When the error is a SyntaxError, with a 400 status, has a `body` property set, and has type `entity.parse.failed`', function() {
const err = getValidError();
const req = {};
const res = {
status: spy(),
set: spy(),
json: spy()
};
const next = spy();
// etc