Carl Rippon

Building SPAs

Carl Rippon
BlogBooks / CoursesAbout
This site uses cookies. Click here to find out more

Mocking Console

March 16, 2022
reacttypescriptjesttests

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

Did you find this post useful?

Let me know by sharing it on Twitter.
Click here to share this post on Twitter

If you to learn more about testing React apps, you may find my course useful:

Testing React Apps with Jest and React Testing Library

Testing React Apps with Jest and React Testing Library
Find out more