Равенство: toBe против toEqual
Урок объясняет ключевую разницу между матчерами toBe и toEqual.
toBe сравнивает по ссылке/значению (как
===), а toEqual сравнивает структуру объектов рекурсивно.
toBe — строгое равенство
toBe использует Object.is, что для примитивов почти совпадает с ===. Идеален для чисел, строк, булевых значений:
expect(2 + 2).toBe(4);
expect('abc').toBe('abc');
expect(true).toBe(true);Но для объектов и массивов toBe проверяет, что это один и тот же объект в памяти. Два разных объекта с одинаковым содержимым по toBe не равны.
Почему toBe не годится для объектов
В JavaScript два литерала {a: 1} — это два разных объекта. Проверим это на живом примере:
const a = { x: 1 };
const b = { x: 1 };
const c = a;
console.log('a === b:', a === b); // разные объекты
console.log('a === c:', a === c); // одна ссылка
console.log('содержимое одинаковое:',
JSON.stringify(a) === JSON.stringify(b));Вывод:
a === b: false a === c: true содержимое одинаковое: true
Видно: содержимое одинаковое, но === (а значит и toBe) считает a и b разными. Поэтому для сравнения структур нужен другой матчер.
toEqual — структурное сравнение
toEqual рекурсивно обходит объект и сравнивает значения всех полей. Содержимое совпадает — тест зелёный, даже если это разные объекты:
expect({ name: 'Аня', age: 30 }).toEqual({ name: 'Аня', age: 30 }); // OK
expect([1, 2, 3]).toEqual([1, 2, 3]); // OK
expect({ name: 'Аня' }).toBe({ name: 'Аня' }); // провал: разные ссылкиТонкость с undefined: toStrictEqual
toEqual игнорирует поля со значением undefined. Если важна и эта разница, используйте toStrictEqual — он также проверяет тип (например, отличает обычный объект от экземпляра класса):
expect({ a: 1, b: undefined }).toEqual({ a: 1 }); // проходит
expect({ a: 1, b: undefined }).toStrictEqual({ a: 1 }); // НЕ проходитПамятка
| Матчер | Когда использовать |
toBe | примитивы (числа, строки, булевы) или проверка той же ссылки |
toEqual | объекты и массивы по содержимому |
toStrictEqual | строгое сравнение, чувствительное к undefined и типу |
Итог
toBe— для примитивов и сравнения ссылок.toEqual— для объектов/массивов по содержимому.- Два разных объекта с одинаковыми полями равны по
toEqual, но не поtoBe. toStrictEqualучитываетundefined-поля и тип.