如何编写一个期望在Jasmine中抛出Error的testing?
我试图为Jasminetesting框架写一个testing,期望有一个错误。 目前我正在使用GitHub的Jasmine Node.js集成 。
在我的节点模块中,我有以下代码:
throw new Error("Parsing is not possible");
现在我试着写一个预期这个错误的testing:
describe('my suite...', function() { [..] it('should not parse foo', function() { [..] expect(parser.parse(raw)).toThrow(new Error("Parsing is not possible")); }); });
我也试过Error()
和其他一些变种,只是不知道如何使其工作。
你应该把一个函数传递给expect(...)
调用。 你在这里的代码:
// incorrect: expect(parser.parse(raw)).toThrow(new Error("Parsing is not possible"));
试图实际调用 parser.parse(raw)
,试图将结果传递给expect(...)
,
尝试使用匿名函数:
expect( function(){ parser.parse(raw); } ).toThrow(new Error("Parsing is not possible"));
您正在使用:
expect(fn).toThrow(e)
但是,如果你看看函数的注释(预期是string):
294 /** 295 * Matcher that checks that the expected exception was thrown by the actual. 296 * 297 * @param {String} expected 298 */ 299 jasmine.Matchers.prototype.toThrow = function(expected) {
我想你应该这样写(使用lambda – 匿名函数):
expect(function() { parser.parse(raw); } ).toThrow("Parsing is not possible");
这在以下示例中得到确认:
expect(function () {throw new Error("Parsing is not possible")}).toThrow("Parsing is not possible");
Douglas Crockford强烈推荐这种方法,而不是使用“抛出新的Error()”(原型方法):
throw { name: "Error", message: "Parsing is not possible" }
我用下面的代替Jasmine的toThrow匹配器,它可以让你匹配exception的名称属性或消息属性。 对我来说,这使得testing更易于编写,而且不易碎,因为我可以这样做:
throw { name: "NoActionProvided", message: "Please specify an 'action' property when configuring the action map." }
然后用以下方法testing:
expect (function () { .. do something }).toThrow ("NoActionProvided");
这让我可以稍后调整exception消息,而不会中断testing,重要的是它抛出了预期types的exception。
这是允许这个的toThrow的替代:
jasmine.Matchers.prototype.toThrow = function(expected) { var result = false; var exception; if (typeof this.actual != 'function') { throw new Error('Actual is not a function'); } try { this.actual(); } catch (e) { exception = e; } if (exception) { result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected) || this.env.equals_(exception.name, expected)); } var not = this.isNot ? "not " : ""; this.message = function() { if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) { return ["Expected function " + not + "to throw", expected ? expected.name || expected.message || expected : " an exception", ", but it threw", exception.name || exception.message || exception].join(' '); } else { return "Expected function to throw an exception."; } }; return result; };
比创build一个唯一目的的匿名函数更优雅的解决scheme是包装另一个,就是使用es5的bind
函数。 bind函数创build一个新的函数,当被调用时,它的this
关键字被设置为提供的值,并且在调用新函数之前提供的任何前面给定的参数序列。
代替:
expect(function () { parser.parse(raw, config); } ).toThrow("Parsing is not possible");
考虑:
expect(parser.parse.bind(parser, raw, config)).toThrow("Parsing is not possible");
绑定语法允许您使用不同的值来testing函数,并且在我看来使testing更具可读性。 另请参阅: https : //stackoverflow.com/a/13233194/1248889
我知道这是更多的代码,但你也可以这样做:
try do something @fail Error("should send a Exception") catch e expect(e.name).toBe "BLA_ERROR" expect(e.message).toBe 'Message'
为咖啡爱好者
expect( => someMethodCall(arg1, arg2)).toThrow()
如前所述,函数需要传递给toThrow
因为它是你在testing中描述的函数:“我希望这个函数抛出x”
expect(() => parser.parse(raw)).toThrow(new Error('Parsing is not possible'));
如果使用Jasmine-Matchers ,则在适合情况时也可以使用下列之一:
// I just want to know that an error was thrown and nothing more about it expect(() => parser.parse(raw)).toThrowAnyError();
要么
// I just want to know that an error of a given type was thrown and nothing more expect(() => parser.parse(raw)).toThrowErrorOfType(TypeError);