按照本 blog post 中解释的 Kent C Dodds 提供者模式,我有一个上下文提供者组件以及一个使用该上下文的钩子。
钩子防止在提供者之外使用它,
export function useUser() {
const { user } = useContext(UserContext) || {};
const { switchUser } = useContext(SwitchUserContext) || {};
if (!user || !switchUser) {
throw new Error('Cannot use `useUser` outside of `UserProvider`');
}
return { user, switchUser };
}
为了测试场景,我创建了一个 TestComponent
并在其中使用了 useUser
钩子。
function TestComponent() {
const { user, switchUser } = useUser();
return (
<>
<p>User: {user.name}</p>
<button onClick={switchUser}>Switch user</button>
</>
);
}
我是这样测试的,
test('should throw error when not wrapped inside `UserProvider`', () => {
const err = console.error;
console.error = jest.fn();
let actualErrorMsg;
try {
render(<TestComponent />);
} catch(e) {
actualErrorMsg = e.message;
}
const expectedErrorMsg = 'Cannot use `useUser` outside of `UserProvider`';
expect(actualErrorMsg).toEqual(expectedErrorMsg);
console.error = err;
});
我目前必须模拟 console.error
,然后在测试结束时将其设置为其原始值。有用。但我想让它更具声明性和更简单。有没有好的模式来实现它?
可能使用 .toThrow() 的东西?
我有一个 codesandbox,上面的代码可以在 UserContext.js
和 UserContext.test.js
中找到。
注意:测试可以在 Tests
标签下的代码和框本身中运行。
答案 0 :(得分:4)
正如您已经提到的,有 expect().toThrow()
:)
所以在你的情况下:
test("should throw error when not wrapped inside `UserProvider`", () => {
expect(() => render(<TestComponent />))
.toThrow("Cannot use `useUser` outside of `UserProvider`");
});
关于 console.error
:
目前,设计上无法关闭默认错误日志。
如果你想隐藏错误,你仍然需要模拟 console.error
。
当您模拟 console.error
等函数时,您希望在 afterEach
回调中恢复它们,以便在测试失败时也能恢复它们。
答案 1 :(得分:0)
你可以这样做
test('should throw error when not wrapped inside `UserProvider`', () => {
component.useUser = jest.fn().mockRejectedValue(new Error('Cannot use `useUser` outside of `UserProvider`'));
let actualErrorMsg;
try {
render(<TestComponent />);
} catch(e) {
actualErrorMsg = e.message;
}
const expectedErrorMsg = 'Cannot use `useUser` outside of `UserProvider`';
expect(actualErrorMsg).toEqual(expectedErrorMsg);
});