Javascript 如何在 Jest 中测试抛出的异常类型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/46042613/
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 test type of thrown exception in Jest
提问by Tranotheron
I'm working with some code where I need to test type of exception thrown by function (Is it TypeError, ReferenceError etc.).
我正在处理一些代码,我需要测试函数抛出的异常类型(是 TypeError、ReferenceError 等)。
My current testing framework is AVA and I can test it as a second argument t.throwsmethod, like here:
我当前的测试框架是 AVA,我可以将它作为第二个参数t.throws方法进行测试,如下所示:
it('should throw Error with message \'UNKNOWN ERROR\' when no params were passed', (t) => {
const error = t.throws(() => {
throwError();
}, TypeError);
t.is(error.message, 'UNKNOWN ERROR');
});
I started rewriting my tests to Jest and couldn't find how to easily do that. Is it even possible?
我开始用 Jest 重写我的测试,但找不到如何轻松做到这一点。甚至有可能吗?
回答by PeterDanis
In Jest you have to pass a function into expect(function).toThrow(blank or type of error).
在 Jest 中,您必须将函数传递给 expect(function).toThrow(blank or type of error)。
Example:
例子:
test("Test description", () => {
const t = () => {
throw new TypeError();
};
expect(t).toThrow(TypeError);
});
If you need to test an existing function whether it throws with a set of arguments, you have to wrap it inside an anonymous function in expect().
如果您需要测试现有函数是否使用一组参数抛出,则必须将其包装在 expect() 中的匿名函数中。
Example:
例子:
test("Test description", () => {
expect(() => {http.get(yourUrl, yourCallbackFn)}).toThrow(TypeError);
});
回答by bodolsog
Little bit weird, but works and imho is good readable:
有点奇怪,但有效,恕我直言,可读性很好:
it('should throw Error with message \'UNKNOWN ERROR\' when no params were passed', () => {
try {
throwError();
// Fail test if above expression doesn't throw anything.
expect(true).toBe(false);
} catch (e) {
expect(e.message).toBe("UNKNOWN ERROR");
}
});
Catchblock catch your exception, then you can test on your raised Error. Strange expect(true).toBe(false);is needed to fail your test if expected Errorwill be not thrown. Otherwise, this line is never reachable (Errorshould be raised before them).
Catch阻止捕获您的异常,然后您可以测试您提出的Error. expect(true).toBe(false);如果预期Error不会抛出,则需要奇怪才能使您的测试失败。否则,这条线永远无法到达(Error应该在他们之前提出)。
EDIT: @Kenny Body suggests a better solution which improve a code quality if you use expect.assertions()
编辑:@Kenny Body 提出了一个更好的解决方案,如果您使用它可以提高代码质量 expect.assertions()
it('should throw Error with message \'UNKNOWN ERROR\' when no params were passed', () => {
expect.assertions(1);
try {
throwError();
} catch (e) {
expect(e.message).toBe("UNKNOWN ERROR");
}
});
See the original answer with more explanations: How to test type of thrown exception in Jest
请参阅更多解释的原始答案:How to test type of throwed exception in Jest
回答by Tal Joffe
I use a slightly more concise version:
我使用了一个稍微简洁的版本:
expect(() => {
//code block that should throw error
}).toThrow(TypeError) //or .toThrow('expectedErrorMessage')
回答by Kenny Body
From my (albeit limited) exposure to Jest, I have found that expect().toThrow()is suitable if you want to ONLY test an error is thrown with a specific message:
从我(尽管有限)接触 Jest 的经验来看,我发现expect().toThrow()如果您只想测试一个带有特定消息的错误,这是合适的:
expect(() => functionUnderTest()).toThrow(TypeError);
expect(() => functionUnderTest()).toThrow(TypeError);
OR an error is thrown of a specific type:
或抛出特定类型的错误:
expect(() => functionUnderTest()).toThrow('Something bad happened!');
expect(() => functionUnderTest()).toThrow('Something bad happened!');
If you try to do both, you will get a false positive. For example if your code throws RangeError('Something bad happened!'), this test will pass:
如果您尝试同时执行这两项操作,则会得到误报。例如,如果您的代码抛出RangeError('Something bad happened!'),则此测试将通过:
expect(() => functionUnderTest()).toThrow(new TypeError('Something bad happened!'));
expect(() => functionUnderTest()).toThrow(new TypeError('Something bad happened!'));
The answer by bodolsog which suggests using a try/catch is close, but rather than expecting true to be false to ensure the expect assertions in the catch are hit, you can instead use expect.assertions(2)at the start of your test where 2is the number of expected assertions. I feel this more accurately describes the intention of the test.
bodolsog 建议使用 try/catch 的答案很接近,但与其期望 true 为 false 以确保命中中的期望断言,不如expect.assertions(2)在测试开始时使用where 2is the number of expected assertions . 我觉得这更准确地描述了测试的意图。
Full example of testing the type AND message of an error:
测试错误类型 AND 消息的完整示例:
describe('functionUnderTest', () => {
it('should throw a specific type of error.', () => {
expect.assertions(2);
try {
functionUnderTest();
} catch (error) {
expect(error).toBeInstanceOf(TypeError);
expect(error).toHaveProperty('message', 'Something bad happened!');
}
});
});
If functionUnderTest()does NOT throw an error, the assertions will be be hit but the expect.assertions(2)will fail and the test will fail.
如果functionUnderTest()不抛出错误,断言将被命中,但expect.assertions(2)将失败并且测试将失败。
回答by Andrei CACIO
Haven't tried it myself but I would suggest using Jest's toThrowassertion. So I guess your example would look something like this:
我自己还没有尝试过,但我建议使用 Jest 的toThrow断言。所以我想你的例子看起来像这样:
it('should throw Error with message \'UNKNOWN ERROR\' when no params were passed', (t) => {
const error = t.throws(() => {
throwError();
}, TypeError);
expect(t).toThrowError('UNKNOWN ERROR');
//or
expect(t).toThrowError(TypeError);
});
Again, haven't test it but I think it should work.
同样,还没有测试它,但我认为它应该可以工作。
回答by alexmac
回答by Slava Baginov
Modern jest allows you to make more checks on rejected value. For example:
现代笑话允许您对拒绝值进行更多检查。例如:
const request = Promise.reject({statusCode: 404})
await expect(request).rejects.toMatchObject({ statusCode: 500 });
will fail with error
会因错误而失败
Error: expect(received).rejects.toMatchObject(expected)
- Expected
+ Received
Object {
- "statusCode": 500,
+ "statusCode": 404,
}
回答by Gilbert
The documentationis clear on how to do this. Let's say I have a function that takes two parameters and it will throw an error if one of them is null.
该文件是如何做到这一点。假设我有一个带有两个参数的函数,如果其中一个是null.
function concatStr(str1, str2) {
const isStr1 = str1 === null
const isStr2 = str2 === null
if(isStr1 || isStr2) {
throw "Parameters can't be null"
}
... // continue your code
Your test
你的测试
describe("errors", () => {
it("should error if any is null", () => {
// notice that the expect has a function that returns the function under test
expect(() => concatStr(null, "test")).toThrow()
})
})
回答by kpollock
I ended up writing a convenience method for our test-utils library
我最终为我们的 test-utils 库编写了一个方便的方法
/**
* Utility method to test for a specific error class and message in Jest
* @param {fn, expectedErrorClass, expectedErrorMessage }
* @example failTest({
fn: () => {
return new MyObject({
param: 'stuff'
})
},
expectedErrorClass: MyError,
expectedErrorMessage: 'stuff not yet implemented'
})
*/
failTest: ({ fn, expectedErrorClass, expectedErrorMessage }) => {
try {
fn()
expect(true).toBeFalsy()
} catch (err) {
let isExpectedErr = err instanceof expectedErrorClass
expect(isExpectedErr).toBeTruthy()
expect(err.message).toBe(expectedErrorMessage)
}
}
回答by ?eljko ?evi?
In case you are working with Promises:
如果您正在使用Promises:
await expect(Promise.reject(new HttpException('Error message', 402)))
.rejects.toThrowError(HttpException);

