Mocks aren’t evil! Better mocking with React Testing Library
Tags: javascript, react, testing
Published: 2020-09-07 20:19:31

---
title: Mocks aren’t evil! Better mocking with React Testing Library
published: true
description: Mocks aren’t evil! They can help you build simpler, more resilient tests. Here’s a guide to using mocks well.
tags: javascript, react, testing 
series: Mocking React components with Testing Library
---

Mocks aren’t evil!

They can help you build simpler, more resilient tests. In this series I’ll show you the patterns I use when writing React component mocks.

Here’s a quick example of a component mock. I’m using `jest.mock` here, which we’ll look at in more detail below.

```javascript
jest.mock("../src/PostContent", () => ({
  PostContent: jest.fn(() => (
    <div data-testid="PostContent" />
  ))
}))
```

React component mocks don’t get much more complicated than this. The important thing is that it has a very simple stub value (the `div`) and a `data-testid` attribute that allows us to find the rendered instance very easily in the DOM. By convention, the test ID used is always the same as the component name. In this case, that’s `PostContent`.

Before we look at how this is used, let’s just recap what mocks are and why you might want to use them.

###What’s a mock?

In the JavaScript world, the term _mock_ is very loosely applied to mean any _test double_. Test doubles are simply values that replace others in your production code while tests run. They take on the interface of the object they’re replacing so that the rest of your code operates as if it hadn’t been replaced.

There are a few different reasons why you’d want to do this; we’ll cover them in examples.

If you’re curious about test doubles in general then I suggest reading Martin Fowler’s [Mocks Aren't Stubs](https://martinfowler.com/articles/mocksArentStubs.html).

###Jest and mocking

Jest has a function called `jest.mock` that allows you to mock out entire modules that you’re replacing. This is what I’m using in this guide, although there are other ways of replacing objects in JavaScript.

> In [Mastering React Test-Driven Development](https://www.packtpub.com/product/mastering-react-test-driven-development/9781789133417) I use ES6 named module imports to create test doubles. That approaches gives slightly more flexibility but feels slightly more hacky.

[The Jest page on `jest.mock`](https://jestjs.io/docs/en/manual-mocks) says that mocks _ensure your tests are fast and not flaky_.

While that’s true, **it’s not the primary reason why I use mocks**. 

I use mocks because they help me keep my tests **independent** of each other.

To see why that is, let’s look at an example.

###Why mocks?

Below is the listing for the `BlogPage` component, which has two jobs: it pulls an `id` out of a `url` prop and it then renders a `PostContent` component with that `id`.

```javascript
const getPostIdFromUrl = url =>
  url.substr(url.lastIndexOf("/") + 1)

export const BlogPage = ({ url }) => {

  const id = getPostIdFromUrl(url)

  return (
    <PostContent id={id} />
  )
}
```

Imagine you’ve been writing tests for this component, and all of your tests go into `BlogPage.test.js`, which is a single test suite that covers both the `BlogPage` and the `PostContent` components.

At this stage you have no need for mocks: we haven’t seen `PostContent` yet, but given the size of `BlogPage` there’s really no need to have two separate test suites, since `BlogPage` is _mostly_ just `PostContent`.

To stretch your imagination further, now pretend that both `BlogPage` and `PostContent` grow in functionality. You, being the gifted developer that you are, are adding more and more features each day.

Keeping your tests in a working state is starting to prove difficult. Each new test has more elaborate set up, and the test suite is becoming a time sink. It’s a burden to maintain.

This is a common problem, and I see it all the time with React codebases. Test suites where even the simplest change causes many tests to break.

One solution to this is to split the test suites. We’ll keep  `BlogPage.test.js` and create a new `PostContent.test.js`, which should house tests specifically for behavior in `PostContent`. The basic idea is that any functionality that’s housed in `PostContent` should be specified in `PostContent.test.js`, and any functionality that’s housed in `BlogPage` (like the URL parsing) should be in `BlogPage.test.js`.

Fine.

But what if rendering `PostContent` has side effects?

```javascript
export const PostContent = ({ id }) => {
  const [ text, setText ] = useState("")

  useEffect(() => {
    fetchPostContent(id)
  }, [id])

  const fetchPostContent = async () => {
    const result = await fetch(`/post?id=${id}`)
    if (result.ok) {
      setText(await result.text())
    }
  }

  return <p>{text}</p>
};
```

The test suite in `BlogPage.test.js` needs to be aware of the side effects and be ready to handle them. For example, it will need to have a `fetch` response lined up and waiting.

**The dependency that we’ve tried to remove by splitting our test suites is still there**.

Our test organization is better for sure, but nothing’s ultimately changed that causes our tests to be less brittle.

For that we need to **stub out** (or mock) `PostContent`.

In the next part we’ll look at how to do that.

###Is this really necessary?

By the way, this is when you move from the realm of **end-to-end tests** and into the realm of **unit tests**.

>The presence of test doubles is a key indicator that you’re writing unit tests.

Many experienced testers will immediately start new projects with unit tests (and mocks) because they know that as their codebase grows they’ll face this problem of test brittleness.

---

_Unit tests tend to be much smaller than end-to-end tests. So small that they’re often not much more than three or four lines of code. That makes them excellent candidates for **social coding** practices like pair and ensemble programming._

---

Even when we’re unit testing, test doubles aren’t always necessary—it’s just another tool in your toolbox that you should know when and how to apply.

In the next part, [I’ll look at basic mocking techniques](https://dev.to/d_ir/the-basic-form-for-react-component-mocks-g5).