100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Testing

Snapshot Testing

Understand how Jest's snapshot testing captures serialized output over time, when it's a good fit, and how to manage snapshot files responsibly.

Assertions & MatchersIntermediate9 min readJul 10, 2026
Analogies

What Is Snapshot Testing

Snapshot testing captures a serialized representation of a value, such as a React component tree, a large configuration object, or an API response, and saves it to a file the first time the test runs. On every subsequent run, Jest re-serializes the current value and compares it character-for-character against the stored snapshot; if they differ, the test fails and shows a diff. This trades writing individual property assertions for a single broad comparison, which is efficient for catching unintended changes but says nothing about whether the originally captured output was actually correct.

🏏

Cricket analogy: Snapshot testing is like photographing the exact field placement at the start of an over so you can instantly spot if a fielder moves without permission mid-over, though the photo itself doesn't confirm the original placement was tactically sound.

Creating and Updating Snapshots

Calling expect(value).toMatchSnapshot() inside a test creates a new snapshot file the first time it runs, typically stored in a __snapshots__ directory next to the test file with a .snap extension, and Jest auto-generates the file if it doesn't exist yet. When the underlying code changes intentionally, the snapshot comparison will fail on the next run; running Jest with the -u (or --updateSnapshot) flag regenerates the stored snapshots to match the new output, which should be a deliberate, reviewed action rather than a reflex response to any failing snapshot test.

🏏

Cricket analogy: Updating a snapshot is like a groundskeeper deliberately re-marking the official pitch dimensions after an approved renovation, a formal, considered action, not something done reflexively every time a measurement looks slightly different from the file.

javascript
function formatInvoice(invoice) {
  return {
    id: invoice.id,
    total: `$${invoice.total.toFixed(2)}`,
    lineItems: invoice.items.map(i => `${i.qty}x ${i.name}`),
  };
}

test('formats an invoice consistently', () => {
  const invoice = { id: 'INV-1', total: 42.5, items: [{ qty: 2, name: 'Widget' }] };
  expect(formatInvoice(invoice)).toMatchSnapshot();
});

// Run `jest -u` to intentionally regenerate this snapshot after a
// reviewed, approved change to formatInvoice's output.

Never run jest -u reflexively just to make a red test suite pass. Read the diff first: if it reveals an unintended change, that's the snapshot test doing its job by catching a real regression, and the underlying code (not the snapshot) needs the fix.

Inline Snapshots

toMatchInlineSnapshot() works the same way as toMatchSnapshot() but writes the serialized value directly into the test file as a string literal argument, right next to the assertion, instead of a separate .snap file. This keeps small, focused snapshots visible in code review without needing to open a second file, which is especially useful for short outputs like a formatted string or a small object, though it becomes unwieldy for large component trees where a separate snapshot file keeps the test file readable.

🏏

Cricket analogy: Inline snapshots are like writing a fielding change directly into the scorer's running commentary at the moment it happens, rather than filing it in a separate log book you'd need to cross-reference later.

javascript
test('formats a short greeting inline', () => {
  const greeting = formatGreeting('Ada');
  expect(greeting).toMatchInlineSnapshot(`"Hello, Ada!"`);
});

When to Use (and Avoid) Snapshots

Snapshots work best for output that is stable, deterministic, and meaningfully reviewed by a human at the moment it's created, such as a rendered component's DOM structure or a formatted report string; the reviewer approving the initial snapshot (and every subsequent -u update) is what gives the test its value. Snapshots work poorly for large, frequently-changing objects, output containing non-deterministic values like timestamps or random IDs (which should be normalized or mocked before snapshotting), and situations where developers are likely to run -u reflexively without reading the diff, since an unreviewed snapshot update simply enshrines whatever the code currently does, bugs included.

🏏

Cricket analogy: Good snapshot use is like keeping an official, human-verified pitch report before a Test match, reviewed by the curator; bad use is like blindly re-certifying the pitch report every single day without anyone actually walking the pitch to check it.

For non-deterministic values like Date.now() or generated UUIDs, use property matchers such as expect.any(String) inside toMatchSnapshot({ createdAt: expect.any(String) }), or mock the underlying source, so the snapshot doesn't fail on every run purely due to a changing timestamp.

  • toMatchSnapshot() serializes a value and compares it against a stored .snap file on every run.
  • The first run creates the snapshot; later runs fail if the serialized output differs.
  • Running jest -u regenerates snapshots and should follow a deliberate review of the diff.
  • toMatchInlineSnapshot() stores the snapshot directly in the test file for small, focused outputs.
  • Snapshots are only as trustworthy as the human review behind the initial capture and every update.
  • Avoid snapshotting non-deterministic data like timestamps or random IDs without normalizing them first.
  • Large, frequently-changing objects are a poor fit for snapshot testing and often lead to reflexive -u updates.

Practice what you learned

Was this page helpful?

Topics covered

#Testing#JestStudyNotes#TestingQA#SnapshotTesting#Snapshot#Creating#Updating#Snapshots#StudyNotes#SkillVeris