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.
Learn React with TypeScript - 3rd Edition
NewA comprehensive guide to building modern React applications with TypeScript. Learn best practices, advanced patterns, and real-world development techniques.
View on Amazon