The Merits of Mocking
What are you doing when you mock something, and when is it worth the cost?
> The more your tests resemble the way your software is used, the more confidence they can give you. — me
One of the biggest challenges people face with testing is knowing what to test. There are lots of reasons for that, but one big, flashing-lights reason is mocking. Many people don’t know when to add a mock version of code or have their test run the actual code directly. These are challenges I’ll help you work through in the JavaScript Mocking Fundamentals module of my Testing JavaScript course.
Mocking lets you fake it ‘til you make it. If you couldn’t have a fake version of certain modules or services, testing the checkout process of an app would cost you a lot of money in credit card fees. Talk about paying a high price for confidence! 🤑 So instead, we make a fake version of that credit card charging service to avoid paying the fees.
But mocking comes with a cost of its own.
Mocking severs the real-world connection between what you’re testing and what you’re mocking. Even if we have confidence that our code works with our fake version of the credit card service, we can’t have 100% confidence that our code will work in production with the real version of the credit card service.
When you mock something, you’re making a trade-off. You’re trading confidence for something else. For me, that something else is usually practicality—meaning I wouldn’t be able to test this thing at all, or it may be pretty difficult/messy, without mocking. (Like in our credit card example.)
In my UI unit and integration tests, I have a rule. I never make actual network calls; instead, I’ll mock the server response by mocking the module responsible for making the network calls. I’ll also mock animation libraries to avoid waiting for animations before elements are removed from the page. Other than that, most of my UI tests are using the real production code. For E2E tests, I avoid mocking anything (with the exception of the backend hitting fake or test services and not actual credit card services, for example).
Saving a few milliseconds per test? That’s not a good reason to mock. People like shallow rendering—component mocking to the max—because it’s faster. That’s true, but we’re talking milliseconds faster. If it takes a long time to render your entire component tree, sounds to me like you have a real performance bug in your software that needs to be addressed. I realize that time adds up (50ms per test * 1000 tests = 50 seconds). But the less you mock, the fewer tests you need, and trading confidence for a minute or two faster test suite is a bad trade. 😵
There’s a time and a place for mocking. And when you need to mock, Jest makes it easy with some really sweet mocking utilities. In testingjavascript.com I’ll show you how to implement some of Jest’s mocking capabilities in raw node so you can get an idea of what’s going on. It’s brilliant. Here’s an example of simulating Jest’s inline mock functionality in pure node:
function fn(impl = () => {}) { const mockFn = (...args) => { mockFn.mock.calls.push(args) return impl(...args) } mockFn.mock = {calls: []} return mockFn } const utilsPath = require.resolve('../utils') require.cache[utilsPath] = { id: utilsPath, filename: utilsPath, loaded: true, exports: { getWinner: fn((p1, p2) => p1) } }
Now, any code that requires that utils module will get the mock function version of that module.
It’s not quite as capable as Jest’s inline mocking abilities, but we’ll cover that in more hands-on detail in the JavaScript Mocking Fundamentals module of the course!
See you in there.
—Kent.
Things to not miss:
- SCHEDULED LIVESTREAMS!: For the next two weeks I’m doing scheduled livestreams every weekday with specific topics. Add this to your calendar and join live to ask questions and get answers.
- Episode 061 – React with Kent C. Dodds on The 6 Figure Developer podcast.
Some tweets from this last week:
> Here’s a tip to safe yourself some work and headache… > > Don’t solve a problem you don’t have yet, even if you think you may possibly have it in the future. > > Solve the problems you have today. Optimize for change, not for the unknowable future 🔮– Oct 9, 2018
> What version of react are you running in production today? > > If you don’t answer latest, why not? You should spend some time upgrading! 👌 – Oct 12, 2018 (This is a poll)
> npx is definitely on the list of my favorite pieces of software that was developed in the last year. I love this thing. > > medium.com/@maybekatz/int… > > Thanks @maybekatz 👏 – Oct 9, 2018
> My wife asked me to draw what I want my birthday cake to look like. > > This is the city setting for my novel 😆 – Oct 14, 2018 (please don’t tweet me about how unoriginal it is…)
> Yesterday I had the pleasure of interviewing @KentBeck for testingjavascript.com and let me just tell you it was awesome. Also very fun to talk with someone who has the same name as I do! > > Thanks Kent! – Oct 12, 2018
This week’s blog post is “Why you’ve been bad about testing”. It’s the published version of my newsletter from 2 weeks ago. If you thought it was good, go ahead and give it some claps (👏x50) and a retweet:
P.S. If you like this, make sure to subscribe, follow me on twitter, buy me lunch, support me on patreon, and share this with your friends 😀
👋 Hi! I’m Kent C. Dodds. I work at PayPal as a full stack JavaScript engineer. I represent PayPal on the TC39. I’m actively involved in the open source community. I’m an instructor on egghead.io and Frontend Masters. I’m also a Google Developer Expert. I’m happily married and the father of four kids. I like my family, code, JavaScript, and React.