Mocking Console
When developing a reusable component, there are cases when we want to warn consumers when they pass a bad props combination. This post covers how to mock console.warn
in a test and verify a warning appears for a bad props combination.
A component to test
The following component warns consumers when the value
and defaultValue
props are both passed:
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} />;
}
The warning is an important bit of logic that we might want to cover in a test. Here’s the skeleton test:
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
});
Using jest.spyOn
A previous post covered how to use jest.spyOn
to mock a function. We can use jest.spyOn
to mock 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
});
The mock implementation doesn’t need to do anything - the main thing is that we can detect that it is called.
We can use the toBeCalledWith
matcher to check that console.warn
is called:
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" );});
At the end of the test, we can call mockRestore
to clear all the mock stats and restore the original implementation of 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();});
Nice! 😊
The code from this post is available in Codesandbox in the link below.
Did you find this post useful?
Let me know by sharing it on Twitter.If you to learn more about testing React apps, you may find my course useful: