Использование expect

Mocha является популярной библиотекой для тестирования JavaScript, предоставляющей структуру для организации тестов и выполнения их с помощью различных утверждений. Одним из основных инструментов для проверки результатов в Mocha является библиотека Chai, которая предоставляет несколько методов утверждений, включая expect. В этом разделе будет рассмотрено, как использовать expect для написания выразительных и легко поддерживаемых тестов.

Установка и настройка

Для начала работы с Mocha и Chai, необходимо установить их через npm. В проекте нужно выполнить следующую команду:

npm install --save-dev mocha chai

После этого можно подключить библиотеки в файле с тестами:

const expect = require('chai').expect;

С этой настройкой можно приступать к использованию expect в тестах.

Основы использования expect

Метод expect позволяет создавать утверждения, которые проверяют, что значения удовлетворяют определённым условиям. expect обычно используется в следующих формах:

expect(значение).to.условие();

Простейший пример использования:

const sum = (a, b) => a + b;

describe('Тестирование функции sum', function() {
  it('должна возвращать правильную сумму', function() {
    expect(sum(2, 3)).to.equal(5);
  });
});

Здесь функция sum суммирует два числа, а утверждение проверяет, что результат действительно равен 5.

Основные методы expect

.to.equal()

Метод .equal() используется для строгого сравнения значений. Это означает, что он проверяет как значение, так и тип данных:

expect(3).to.equal(3);  // Успешно
expect(3).to.equal('3'); // Ошибка, типы данных разные
.to.deep.equal()

Метод .deep.equal() предназначен для глубокого сравнения объектов и массивов. Он проверяет, что содержимое объектов или массивов одинаково, а не только ссылки на них:

const obj1 = { a: 1, b: 2 };
const obj2 = { a: 1, b: 2 };
expect(obj1).to.deep.equal(obj2); // Успешно
.to.be.ok

Метод .ok проверяет, что выражение истинно, т.е. оно не является null, undefined, false, 0 или пустой строкой:

expect(true).to.be.ok;    // Успешно
expect(1).to.be.ok;       // Успешно
expect('').to.not.be.ok;  // Ошибка
.to.be.a()

Метод .a() используется для проверки типа значения. Он может проверять как примитивные типы, так и объекты:

expect('Hello').to.be.a('string');   // Успешно
expect(42).to.be.a('number');        // Успешно
expect([1, 2, 3]).to.be.a('array');  // Ошибка, массив — это объект
.to.be.an()

Метод .an() работает аналогично .a(), но используется в сочетании с динамическими типами:

expect([1, 2, 3]).to.be.an('array'); // Успешно
expect({ name: 'John' }).to.be.an('object'); // Успешно
.to.have.lengthOf()

Метод .lengthOf() проверяет длину строк, массивов или коллекций:

expect([1, 2, 3]).to.have.lengthOf(3);  // Успешно
expect('Hello').to.have.lengthOf(5);    // Успешно
.to.throw()

Метод .throw() используется для проверки того, что функция выбрасывает исключение. Можно указать конкретное исключение или использовать регулярное выражение для поиска ошибок:

const throwError = () => { throw new Error('Ошибка'); };

expect(throwError).to.throw(); // Успешно
expect(throwError).to.throw('Ошибка'); // Успешно
expect(throwError).to.throw(Error);  // Успешно

Асинхронные тесты с expect

Для тестирования асинхронных функций в Mocha используется механизм done или возвращение промисов. В случае использования expect, также возможно проверять результаты асинхронных операций. Рассмотрим пример с промисом:

const asyncAdd = (a, b) => Promise.resolve(a + b);

describe('Асинхронное тестирование функции asyncAdd', function() {
  it('должна правильно сложить два числа', function() {
    return asyncAdd(2, 3).then(result => {
      expect(result).to.equal(5);
    });
  });
});

Использование промисов и expect позволяет проверять, что асинхронная операция выполнена корректно.

Обработка ошибок

Использование expect позволяет легко проверять ошибки в коде. Метод .to.throw() проверяет, что конкретная ошибка была выброшена. Если ошибки не было, тест завершится неудачей.

Пример с функцией, которая должна выбрасывать ошибку:

const divide = (a, b) => {
  if (b === 0) throw new Error('Деление на ноль');
  return a / b;
};

describe('Тестирование функции divide', function() {
  it('должна выбросить ошибку при делении на ноль', function() {
    expect(() => divide(1, 0)).to.throw('Деление на ноль');
  });
});

В этом примере проверяется, что при делении на ноль будет выброшено исключение с соответствующим сообщением.

Дополнительные возможности

Chai также предоставляет возможности для более специфичных проверок, таких как:

  • Массивы и объекты: .to.include(), .to.have.property()
  • Типы данных: .to.be.null, .to.exist, .to.be.undefined

Например:

const arr = [1, 2, 3];

expect(arr).to.include(2); // Проверка на включение
expect({ name: 'John' }).to.have.property('name'); // Проверка на наличие свойства

Практические рекомендации

  • Читаемость тестов: При использовании expect важно следить за читаемостью тестов. Формулировки должны быть понятны и однозначны, чтобы любой разработчик мог быстро понять, что именно проверяется.

  • Использование в больших проектах: В больших проектах часто используется несколько типов утверждений в одном тесте. Например, можно комбинировать проверки на равенство, тип и наличие свойств, чтобы сделать тесты более полными.

expect(response).to.be.an('object');
expect(response).to.have.property('status').that.equals(200);
expect(response.data).to.be.an('array').that.is.not.empty;
  • Сложные асинхронные операции: При работе с асинхронным кодом важно правильно обрабатывать промисы и колбэки, чтобы тесты не завершались до того, как все проверки будут выполнены. Использование return или done гарантирует, что тест завершится только после выполнения всех операций.

Заключение

Метод expect является мощным инструментом для написания тестов в Mocha, позволяя проверять различные аспекты данных, функций и ошибок в коде. Его выраженный синтаксис и простота использования делают тестирование JavaScript-программ лёгким и эффективным.