Javascript 如何编写一个期望在 Jasmine 中抛出错误的测试?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4144686/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to write a test which expects an Error to be thrown in Jasmine?
提问by echox
I'm trying to write a test for the Jasmine Test Frameworkwhich expects an error. At the moment I'm using a Jasmine Node.js integration from GitHub.
我正在尝试为Jasmine 测试框架编写一个预计会出错的测试。目前我正在使用来自 GitHub的Jasmine Node.js 集成。
In my Node module I have the following code:
在我的 Node 模块中,我有以下代码:
throw new Error("Parsing is not possible");
Now I try to write a test which expects this error:
现在我尝试编写一个预期会出现此错误的测试:
describe('my suite...', function() {
[..]
it('should not parse foo', function() {
[..]
expect(parser.parse(raw)).toThrow(new Error("Parsing is not possible"));
});
});
I tried also Error()
and some other variants and just can't figure out how to make it work.
我也尝试过Error()
和其他一些变体,但无法弄清楚如何使其工作。
回答by Pete Hodgson
you should be passing a function into the expect(...)
call. The code you have here:
您应该将函数传递给expect(...)
调用。你在这里的代码:
// incorrect:
expect(parser.parse(raw)).toThrow(new Error("Parsing is not possible"));
is trying to actually callparser.parse(raw)
in an attempt to pass the result into expect(...)
,
正在尝试实际调用parser.parse(raw)
以尝试将结果传递到expect(...)
,
Try using an anonymous function instead:
尝试改用匿名函数:
expect( function(){ parser.parse(raw); } ).toThrow(new Error("Parsing is not possible"));
回答by Andrzej ?liwa
You are using:
您正在使用:
expect(fn).toThrow(e)
But if you'll have a look on the function comment (expected is 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) {
I suppose you should probably write it like this (using lambda - anonymous function):
我想你应该这样写(使用 lambda - 匿名函数):
expect(function() { parser.parse(raw); } ).toThrow("Parsing is not possible");
This is confirmed in the following example:
这在以下示例中得到证实:
expect(function () {throw new Error("Parsing is not possible")}).toThrow("Parsing is not possible");
Douglas Crockford strongly recommends this approach, instead of using "throw new Error()" (prototyping way):
Douglas Crockford 强烈推荐这种方法,而不是使用“throw new Error()”(原型方法):
throw {
name: "Error",
message: "Parsing is not possible"
}
回答by Jonathan Gawrych
A more elegant solution than creating an anonymous function who's sole purpose is to wrap another, is to use es5's bind
function. The bind function creates a new function that, when called, has its this
keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
比创建一个唯一目的是包装另一个匿名函数的更优雅的解决方案是使用 es5 的bind
函数。bind 函数会创建一个新函数,该函数在调用时将其this
关键字设置为提供的值,并在调用新函数时在任何提供的参数之前提供给定的参数序列。
Instead of:
代替:
expect(function () { parser.parse(raw, config); } ).toThrow("Parsing is not possible");
expect(function () { parser.parse(raw, config); } ).toThrow("Parsing is not possible");
Consider:
考虑:
expect(parser.parse.bind(parser, raw, config)).toThrow("Parsing is not possible");
expect(parser.parse.bind(parser, raw, config)).toThrow("Parsing is not possible");
The bind syntax allows you to test functions with different this
values, and in my opinion makes the test more readable. See also: https://stackoverflow.com/a/13233194/1248889
bind 语法允许您测试具有不同this
值的函数,并且在我看来使测试更具可读性。另见:https: //stackoverflow.com/a/13233194/1248889
回答by Jake
I replace Jasmine's toThrow matcher with the following, which lets you match on the exception's name property or its message property. For me this makes tests easier to write and less brittle, as I can do the following:
我将 Jasmine 的 toThrow 匹配器替换为以下内容,这使您可以匹配异常的 name 属性或其消息属性。对我来说,这使测试更容易编写且不那么脆弱,因为我可以执行以下操作:
throw {
name: "NoActionProvided",
message: "Please specify an 'action' property when configuring the action map."
}
and then test with the following:
然后使用以下内容进行测试:
expect (function () {
.. do something
}).toThrow ("NoActionProvided");
This lets me tweak the exception message later without breaking tests, when the important thing is that it threw the expected type of exception.
这让我稍后可以在不破坏测试的情况下调整异常消息,重要的是它抛出了预期的异常类型。
This is the replacement for toThrow that allows this:
这是 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;
};
回答by Jamie Mason
As mentioned previously, a function needs to be passed to toThrow
as it is the function you're describing in your test: "I expect this function to throw x"
如前所述,需要传递一个函数,toThrow
因为它是您在测试中描述的函数:“我希望这个函数抛出 x”
expect(() => parser.parse(raw))
.toThrow(new Error('Parsing is not possible'));
If using Jasmine-Matchersyou can also use one of the following when they suit the situation;
如果使用Jasmine-Matchers,您也可以在适合情况时使用以下其中一种;
// I just want to know that an error was
// thrown and nothing more about it
expect(() => parser.parse(raw))
.toThrowAnyError();
or
或者
// I just want to know that an error of
// a given type was thrown and nothing more
expect(() => parser.parse(raw))
.toThrowErrorOfType(TypeError);
回答by tolbard
I know that is more code but you can also do:
我知道这是更多的代码,但你也可以这样做:
try
do something
@fail Error("should send a Exception")
catch e
expect(e.name).toBe "BLA_ERROR"
expect(e.message).toBe 'Message'
回答by fernandohur
For coffeescript lovers
对于咖啡文字爱好者
expect( => someMethodCall(arg1, arg2)).toThrow()
回答by arifaBatool
For anyone who still might be facing this issue, for me the posted solution didn't work and it kept on throwing this error: Error: Expected function to throw an exception.
I later realised that the function which I was expecting to throw an error was an async function and was expecting promise to be rejected and then throw error and that's what I was doing in my code:
对于仍然可能面临这个问题的任何人,对我来说,发布的解决方案不起作用,它不断抛出这个错误:Error: Expected function to throw an exception.
我后来意识到我期望抛出错误的函数是一个异步函数,并期望承诺被拒绝然后抛出错误,这就是我在代码中所做的:
throw new Error('REQUEST ID NOT FOUND');
and thats what I did in my test and it worked:
这就是我在测试中所做的并且它有效:
it('Test should throw error if request not found', willResolve(() => {
const promise = service.getRequestStatus('request-id');
return expectToReject(promise).then((err) => {
expect(err.message).toEqual('REQUEST NOT FOUND');
});
}));