Staying out of trouble
Daniel Irvine 🏳️🌈
Posted on September 7, 2020
This is the final part of a series on React component mocks. We’ll wrap up with a recap and then look at some common difficulties that you’ll encounter.
All the code samples for this post are available at the following repo.
dirv / mocking-react-components
An example of how to mock React components
Mocks are a notoriously difficult testing facility. That’s why some educators don’t use and don’t teach them.
But mastering mocks will make give you an extra weapon to fight brittle, time-sinking tests.
So how can you ensure you stay safe with mocks? Simple: stick to the patterns!
Stick to the patterns
If you stick to the patterns I’ve shown you in this series, you shouldn’t have problems.
Start with the basic mock function which renders a div
with a data-testid
attached. We looked at this in part two.
jest.mock("../src/PostContent", () => ({
PostContent: jest.fn(() => (
<div data-testid="PostContent" />
))
}))
If you need to, you can render children
too. That was described in part three.
jest.mock("../src/PostContent", () => ({
PostContent: jest.fn(({ children }) => (
<div data-testid="PostContent">{children}</div>
))
}))
If you really need to, you can use prop value to make unique data-testid
s. But this is often unnecessary complexity. That was in part four.
jest.mock("../src/PostContent", () => ({
PostContent: jest.fn(({ children, id }) => <div data-testid={`PostContent-${id}`}>{children}</div>)
}))
I always dislike giving any kind of advice on what to avoid: every technique has its place. But if I was to name one thing to be careful about, I’d say it would be building fakes and in particular use of the Jest function mockImplementation
.
Why? Well, a major reason for using spies and stubs is to help build independent test suites that don’t slow you down.
An important way to do that is to restrict your code to a small number of patterns. It’s a little bit like having a set of coding standards, but at a higher level.
When you start building fakes and elaborate mock implementations, you are moving away from that goal because now you have logic within your tests: you can’t glance at them and immediately know how they work. And any change to the production code requires you to re-understand the fake implementation code before inevitably changing that too.
Conversely, when you stick to the handful of mock patterns I’ve shown you, you will get faster and faster at writing tests that use them. That’s because you recognise the patterns and don’t need to re-evaluate them in your brain each time you see them.
What if none of the patterns works for your test suites?
If you’re stuck, the first question to ask yourself is: how testable is my production code?
Because it’s not mocks that are causing you test pain, but production code that isn’t structured for testability.
Improving the testability of your code
The number one problem I see with React codebases is very large components that express many different ideas. Often, new features are just piled on top of each other rather than taking time to sort out abstractions or find a logical organisational structure.
So a good place to start is to split your large components apart.
How large is large? File size is often a good metric to use: for me, anything more than 100 lines is suspect. And many of my components are fewer than 10 lines in size!
What if it’s not obvious how to split a component? Start with the single responsibility principle: each component should do one thing and one thing only.
Of course, the notion of one “thing” leaves you plenty of rope to hang yourself. Figuring out elegant “things” is most of the difficulty in software design.
If you’re interested in this topic then I’d suggest learning about coupling, cohesion and connascence, all of which apply to React components, even though you won’t often hear React educators talking about them.
Where to go from here
In this series I’ve shown you a very specific way to test React components. If you’re interested in more detailed theory and history about these techniques, then take a look at my book, Mastering React Test-Driven Development. It doesn’t use React Testing Library but instead explores testing from first principles. Doing that will give you a much deeper understanding of successful React testing.
Posted on September 7, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.