在开发一个可重用的组件时,有些情况下我们想在消费者通过一个不好的道具组合时发出警告。这篇文章介绍了如何在测试中模拟console.warn ,并验证出现不良道具组合的警告。
要测试的组件
当value 和defaultValue 道具同时被通过时,下面的组件会警告消费者:
export function Input(props: React.ComponentPropsWithoutRef<"input">) {
React.useEffect(() => {
if (props.value !== undefined && props.defaultValue !== undefined) {
console.warn(
"If you are controlling `value` with state, there is no need to pass `defaultValue` - just set the default state"
);
}
}, [props.value, props.defaultValue]);
return <input className="input" {...props} />;
}
这个警告是一个重要的逻辑,我们可能想在测试中涵盖它。下面是测试的骨架:
test("Should output warning when value and defaultValue specified", () => {
// TODO - mock `console.warn`
render(<Input value="test" defaultValue="test" />);
// TODO - check console.warn has been called
});
使用jest.spyOn
上一篇文章介绍了如何使用jest.spyOn 来模拟一个函数。我们可以使用jest.spyOn 来模拟console.warn :
test("Should output warning when value and defaultValue specified", () => {
const warn = jest.spyOn(console, 'warn').mockImplementation(() => {}); render(<Input value="test" defaultValue="test" />);
// TODO - check console.warn has been called
});
模拟实现不需要做任何事情--主要的是我们可以检测到它被调用。
我们可以使用toBeCalledWith 匹配器来检查console.warn 是否被调用:
test("Should output warning when value and defaultValue specified", () => {
const warn = jest.spyOn(console, "warn").mockImplementation(() => {});
render(<Input value="test" defaultValue="test" />);
expect(warn).toBeCalledWith( "If you are controlling `value` with state, there is no need to pass `defaultValue` - just set the default state" );});
在测试结束时,我们可以调用mockRestore 来清除所有的模拟统计,并恢复原始的console.warn 的实现:
test("Should output warning when value and defaultValue specified", () => {
const warn = jest.spyOn(console, "warn").mockImplementation(() => {});
render(<Input value="test" defaultValue="test" />);
expect(warn).toBeCalledWith(
"If you are controlling `value` with state, there is no need to pass `defaultValue` - just set the default state"
);
warn.mockRestore();});
很好!😊
本帖的代码可以在Codesandbox中找到,链接如下: