如何编写一个期望在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);