How to Mock the Cheerio NPM Package with Jest (The Right Way)
If you're writing tests for a Node.js application and using the popular HTML parser cheerio
, chances are you'll want to mock Cheerio in Jest—especially when you don't want your unit tests to depend on real DOM-like structures.
In this article, we’ll explore how to mock the cheerio
library using Jest, why you might want to do it, and how to avoid common pitfalls when mocking external modules.
📦 What Is Cheerio?
cheerio
is a fast, flexible, and lean implementation of core jQuery designed specifically for the server. It's commonly used for:
- Web scraping
- HTML manipulation
- Testing rendered markup
- Parsing SSR content
Cheerio returns a jQuery-like API for traversing and manipulating the DOM on the server. Under the hood, it's powered by htmlparser2
.
🤔 Why Mock Cheerio in Jest?
When testing functions that depend on cheerio
, you might want to:
- Avoid parsing real HTML in every test
- Control the output of
$()
and.find()
- Simulate different DOM structures and behaviors
- Speed up your unit tests by stubbing Cheerio behavior
✅ Step-by-Step: Mocking cheerio
with Jest
Let’s walk through mocking cheerio
in a real-world use case.
1. The Function You Want to Test
Suppose you have a helper function like this:
// scraper.js
const cheerio = require('cheerio');
function extractTitle(html) {
const $ = cheerio.load(html);
return $('title').text();
}
module.exports = { extractTitle };
You want to write a unit test without relying on cheerio.load()
to parse actual HTML.
2. Mocking cheerio
with Jest
You can mock the entire module like this:
// __tests__/scraper.test.js
jest.mock('cheerio', () => {
const mockText = jest.fn();
const mockFind = jest.fn(() => ({ text: mockText }));
const mockLoad = jest.fn(() => (html) => ({
find: mockFind,
text: mockText,
// You can simulate more methods if needed
}));
return {
load: mockLoad,
};
});
Now you can control the output in your test:
3. Writing the Test
const cheerio = require('cheerio');
const { extractTitle } = require('../scraper');
describe('extractTitle', () => {
it('should extract title from HTML', () => {
const fakeText = 'Mock Page Title';
// Simulate `$('title').text()` returning fakeText
cheerio.load.mockReturnValue(() => ({
find: () => ({
text: () => fakeText,
}),
text: () => fakeText,
}));
const result = extractTitle('<html><title>Real Title</title></html>');
expect(result).toBe(fakeText);
});
});
🧪 Alternative: Partial Mocking Using jest.spyOn
If you want to test with real HTML sometimes but still spy on the cheerio.load
method:
const cheerio = require('cheerio');
describe('extractTitle', () => {
it('should call cheerio.load', () => {
const spy = jest.spyOn(cheerio, 'load');
const html = '<html><title>Hello</title></html>';
const { extractTitle } = require('../scraper');
extractTitle(html);
expect(spy).toHaveBeenCalledWith(html);
spy.mockRestore();
});
});
🧠 Pro Tips
- Always reset your mocks between tests:
jest.resetAllMocks();
- Don’t over-mock: Prefer integration-style tests if you're testing HTML parsing behavior.
- Use TypeScript? Add
jest.mocked()
to type your mocks properly.
🔚 Conclusion
Mocking the cheerio
package in Jest is straightforward but requires understanding how Cheerio works under the hood. Whether you want full mocks or partial spies, Jest provides all the tools you need.
By mocking Cheerio, you can write faster, more deterministic tests without worrying about HTML parsing details.