为什么 Mocha/Chai 不将 babel 自定义错误与常规自定义错误一样对待?
Why don't Mocha/Chai treat babel custom errors the same as regular custom errors?
这适用于 Mocha/Chai:
describe('Chai throw() with old-style custom errors', ()=> {
// old way
function ES5Error(message = 'todo', value) {
this.name = 'ES5Error';
this.message = message;
}
ES5Error.prototype = new Error();
it('catches ES5Errors', ()=> {
var err = new ES5Error('This is a bad function.');
var fn = function () { throw err; }
expect(fn).to.throw(ES5Error);
expect(fn).to.throw(Error);
expect(fn).to.throw(/bad function/);
expect(fn).to.not.throw('good function');
expect(fn).to.throw(ES5Error, /bad function/);
expect(fn).to.throw(err);
});
});
虽然基于 class 的方法不会:
describe('Chai throw() with new-style custom errors', ()=> {
// New way
class ExtendError extends Error {
constructor(message = 'todo', value) {
super(message);
this.name = 'ExtendError';
this.message = message;
}
}
it('catches ExtendError', ()=> {
var err = new ExtendError('This is a bad function.');
var fn = function () { throw err; }
expect(fn).to.throw(ExtendError);
expect(fn).to.throw(Error);
expect(fn).to.throw(/bad function/);
expect(fn).to.not.throw('good function');
expect(fn).to.throw(ExtendError, /bad function/);
expect(fn).to.throw(err);
});
});
我也实现了相关的。虽然很有趣,但它仍然不适用于 mocha throws()
。我基本上很乐意使用 ES5 风格的错误,但我只是不确定实际问题是什么。当我转译 ExtendError
的代码时,我无法立即看到任何会触发 expect 子句的内容:
'use strict';
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}
var ExtendError = function (_Error) {
_inherits(ExtendError, _Error);
function ExtendError() {
var message = arguments.length <= 0 || arguments[0] === undefined ? 'todo' : arguments[0];
var value = arguments[1];
_classCallCheck(this, ExtendError);
var _this = _possibleConstructorReturn(this, _Error.call(this, message));
_this.name = 'ExtendError';
_this.message = message;
return _this;
}
return ExtendError;
}(Error);
Mocha/Chai的问题是什么?
问题不在 Chai 身上。如果你用你的 ES6 实现 err instanceof ExtendError
你会得到 false
!
ExtendError
你 运行 的 ES5 和 ES6 实现实际上是不同的。
在 ES5 端,您调用 Error
但不对 return 值执行任何操作。这是正确的。
在ES6端,super(...)
调用转换为
var _this = _possibleConstructorReturn(this, _Error.call(this, message));`
然后_this
取代了原来ES6代码中的this
。 Error
的 return 值在 ES6 代码中使用,这是一切都变得糟糕的地方,因为您然后从构造函数中 return 的对象是一个 Error
对象但不是一个 ExtendError
对象。
我会继续使用 ES5 语法派生自 Error
。我尝试了一些方法来保持 ES6 语法,但最终它们是混合的或者做了非常糟糕的事情。我想到的最不令人反感的方法是:
class ExtendError {
constructor(message = 'todo', value) {
Error.call(this, message);
this.name = 'ExtendError';
this.message = message;
}
}
ExtendError.prototype = Object.create(Error.prototype);
ExtendError.prototype.constructor = ExtendError;
它没有很好地利用 ES6 class
糖...
这适用于 Mocha/Chai:
describe('Chai throw() with old-style custom errors', ()=> {
// old way
function ES5Error(message = 'todo', value) {
this.name = 'ES5Error';
this.message = message;
}
ES5Error.prototype = new Error();
it('catches ES5Errors', ()=> {
var err = new ES5Error('This is a bad function.');
var fn = function () { throw err; }
expect(fn).to.throw(ES5Error);
expect(fn).to.throw(Error);
expect(fn).to.throw(/bad function/);
expect(fn).to.not.throw('good function');
expect(fn).to.throw(ES5Error, /bad function/);
expect(fn).to.throw(err);
});
});
虽然基于 class 的方法不会:
describe('Chai throw() with new-style custom errors', ()=> {
// New way
class ExtendError extends Error {
constructor(message = 'todo', value) {
super(message);
this.name = 'ExtendError';
this.message = message;
}
}
it('catches ExtendError', ()=> {
var err = new ExtendError('This is a bad function.');
var fn = function () { throw err; }
expect(fn).to.throw(ExtendError);
expect(fn).to.throw(Error);
expect(fn).to.throw(/bad function/);
expect(fn).to.not.throw('good function');
expect(fn).to.throw(ExtendError, /bad function/);
expect(fn).to.throw(err);
});
});
我也实现了相关的throws()
。我基本上很乐意使用 ES5 风格的错误,但我只是不确定实际问题是什么。当我转译 ExtendError
的代码时,我无法立即看到任何会触发 expect 子句的内容:
'use strict';
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}
var ExtendError = function (_Error) {
_inherits(ExtendError, _Error);
function ExtendError() {
var message = arguments.length <= 0 || arguments[0] === undefined ? 'todo' : arguments[0];
var value = arguments[1];
_classCallCheck(this, ExtendError);
var _this = _possibleConstructorReturn(this, _Error.call(this, message));
_this.name = 'ExtendError';
_this.message = message;
return _this;
}
return ExtendError;
}(Error);
Mocha/Chai的问题是什么?
问题不在 Chai 身上。如果你用你的 ES6 实现 err instanceof ExtendError
你会得到 false
!
ExtendError
你 运行 的 ES5 和 ES6 实现实际上是不同的。
在 ES5 端,您调用
Error
但不对 return 值执行任何操作。这是正确的。在ES6端,
super(...)
调用转换为var _this = _possibleConstructorReturn(this, _Error.call(this, message));`
然后
_this
取代了原来ES6代码中的this
。Error
的 return 值在 ES6 代码中使用,这是一切都变得糟糕的地方,因为您然后从构造函数中 return 的对象是一个Error
对象但不是一个ExtendError
对象。
我会继续使用 ES5 语法派生自 Error
。我尝试了一些方法来保持 ES6 语法,但最终它们是混合的或者做了非常糟糕的事情。我想到的最不令人反感的方法是:
class ExtendError {
constructor(message = 'todo', value) {
Error.call(this, message);
this.name = 'ExtendError';
this.message = message;
}
}
ExtendError.prototype = Object.create(Error.prototype);
ExtendError.prototype.constructor = ExtendError;
它没有很好地利用 ES6 class
糖...