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.

🏃 Play with the code

Learn React with TypeScript - 3rd Edition

New

A comprehensive guide to building modern React applications with TypeScript. Learn best practices, advanced patterns, and real-world development techniques.

View on Amazon
Learn React with TypeScript - Third Edition