How to Resolve "Received: serializes to the same string" Jest Error in JavaScript
The Jest error Received: serializes to the same string is a helpful message that occurs when you try to compare two objects or arrays using the .toBe() matcher. It's Jest's way of telling you, "These two things look the same when I turn them into strings, but they are not the same object in memory. Did you mean to do a deep equality check?"
This guide will explain the fundamental difference between referential and deep equality, and show you how to solve this error by using the correct matcher, .toEqual() or .toStrictEqual().
The Core Problem: Referential vs. Deep Equality
In JavaScript, objects and arrays (which are a type of object) are reference types. This means that when you compare them, you are comparing their "address" in memory, not their contents.
- Referential Equality (
===or.toBe()): Checks if two variables point to the exact same object in memory. - Deep Equality (
.toEqual()): Checks if two objects have the same contents, recursively comparing all of their properties and values.
The Problem
The .toBe() matcher in Jest uses referential equality. The test below fails because even though the two arrays have the same contents, they are two separate objects in memory.
test('arrays should be equal', () => {
const expected = ['a', 'b', 'c'];
const received = ['a', 'b', 'c'];
// ⛔️ This fails! They are two different arrays in memory.
expect(received).toBe(expected);
});
This is when Jest shows the helpful "serializes to the same string" error message, suggesting you use a different matcher.
The Solution (Recommended): Use .toStrictEqual() or .toEqual()
To fix this error, you must use a matcher that performs a deep equality check. Jest provides two excellent options for this.
The solution is to replace .toBe() with .toStrictEqual().
test('arrays should be equal', () => {
const expected = ['a', 'b', 'c'];
const received = ['a', 'b', 'c'];
// ✅ Correct: This performs a deep comparison of the contents.
expect(received).toStrictEqual(expected); // This passes!
});
test('objects should be equal', () => {
const expected = { id: 1, name: 'Alice' };
const received = { id: 1, name: 'Alice' };
expect(received).toStrictEqual(expected); // This also passes!
});
.toStrictEqual() vs. .toEqual(): Key Differences
Both .toStrictEqual() and .toEqual() perform deep equality checks, but .toStrictEqual() is more rigorous. For this reason, it is generally the recommended best practice.
| Scenario | .toEqual() | .toStrictEqual() | Recommendation |
|---|---|---|---|
| Undefined Properties | Ignores them. {a: 1} equals {a: 1, b: undefined}. | Cares about them. {a: 1} does not equal {a: 1, b: undefined}. | toStrictEqual is safer. |
| Sparse Arrays | Ignores them. [, 1] equals [undefined, 1]. | Cares about them. [, 1] does not equal [undefined, 1]. | toStrictEqual is more precise. |
| Class Instances | Ignores type. new MyClass() equals an object literal with the same properties. | Cares about type. new MyClass() does not equal an object literal. | toStrictEqual is stricter. |
Rule of Thumb: Start with .toStrictEqual(). Only use .toEqual() if you have a specific reason to ignore undefined properties or class types.
When to Use .toBe()
You should only use .toBe() in two scenarios:
- For Primitive Values: It is perfect for comparing numbers, strings, booleans,
null, andundefined.expect(2 + 2).toBe(4);
expect('hello').toBe('hello'); - For Referential Identity: When you need to check if two variables point to the exact same object instance.
const originalArray = [1, 2, 3];
const sameArray = originalArray; // Both variables point to the same array
expect(sameArray).toBe(originalArray); // This passes
A Common Pitfall: Hidden Properties
Sometimes, a test will fail with the "serializes to the same string" error even when using .toEqual(). This can happen if one of the objects has a "hidden" or non-enumerable property that JSON.stringify() (which Jest uses for the error message) ignores, but that the deep equality check detects.
Example of the problem:
const arr1 = ['a', 'b'];
const arr2 = ['a', 'b'];
// Add a non-standard property to one of the arrays
arr2.someOtherProp = 'hidden';
// The toEqual() check will see this property and fail.
expect(arr1).toEqual(arr2); // ⛔️ Fails!
Solution: console.log() both of your objects directly in the test. This will often reveal the extra properties that are causing the deep equality check to fail.
Conclusion
The "Received: serializes to the same string" error is a helpful pointer from Jest, guiding you to use the correct matcher for comparing objects and arrays.
- Use
.toBe()for comparing primitive values or for checking referential identity. - Use
.toStrictEqual()(or.toEqual()) for performing a deep comparison of the contents of objects and arrays. .toStrictEqual()is the recommended best practice as it is more rigorous and catches differences in types andundefinedproperties.