Unit тесты играют важную роль в процессе разработки приложений, позволяя проверять работоспособность отдельных частей кода, таких как модели, компоненты и сервисы. В Ember.js, как и в других фреймворках, важно обеспечить корректную работу каждого модуля, минимизируя вероятность ошибок при их интеграции. Эта глава посвящена основам написания unit тестов в Ember.js с использованием встроенного тестового фреймворка.
Ember.js использует фреймворк QUnit для написания тестов. QUnit — это мощный инструмент, который предоставляет удобные API для тестирования JavaScript-кода. В Ember.js тестирование реализуется через систему тестирования, встроенную в Ember CLI, которая настроена для работы с QUnit, а также с Mocha и Chai, если они используются в проекте.
Важной особенностью тестирования в Ember является то, что оно тесно связано с архитектурой фреймворка. Компоненты, модели и контроллеры, как правило, пишутся с учётом того, что их поведение будет проверяться с помощью unit тестов.
Тесты в Ember.js обычно организованы в директории
tests/unit, где каждый модуль (модель, компонент, сервис и
т. д.) имеет свой файл теста. Тесты могут выглядеть следующим
образом:
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Model | user', function(hooks) {
setupTest(hooks);
test('имя пользователя возвращается корректно', function(assert) {
let store = this.owner.lookup('service:store');
let user = store.createRecord('user', { name: 'Иван' });
assert.equal(user.name, 'Иван', 'Имя пользователя корректно установлено');
});
});
Здесь используется:
module — для создания группы тестов (с возможностью
настройки перед каждым тестом).test — для самого теста, который проверяет конкретное
поведение.setupTest — для настройки окружения теста, например,
для подключения к хранилищу.При тестировании моделей важно проверить, что они корректно работают с данными и возвращают правильные значения. В Ember.js модели связаны с хранилищем данных (store), которое позволяет создавать записи и управлять их состоянием.
Пример теста для модели:
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Model | user', function(hooks) {
setupTest(hooks);
test('проверка, что модель возвращает правильное имя', function(assert) {
let store = this.owner.lookup('service:store');
let user = store.createRecord('user', { name: 'Алексей' });
assert.equal(user.get('name'), 'Алексей');
});
test('проверка валидации email', function(assert) {
let store = this.owner.lookup('service:store');
let user = store.createRecord('user', { email: 'invalid-email' });
assert.notOk(user.get('isValid'), 'Email некорректен');
});
});
Здесь проверяется не только корректность данных, но и валидация модели. Тестирование моделей — это важная часть, так как модели чаще всего содержат бизнес-логику, и важно, чтобы она работала правильно.
Компоненты — одна из ключевых сущностей в Ember.js, которые представляют собой переиспользуемые части UI. Unit тестирование компонентов позволяет проверить их поведение и отображение.
Пример теста для компонента:
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
module('Integration | Component | user-card', function(hooks) {
setupRenderingTest(hooks);
test('компонент отображает имя пользователя', async function(assert) {
this.set('user', { name: 'Марина' });
await render(hbs`<UserCard @user={{this.user}} />`);
assert.dom('.user-name').hasText('Марина', 'Имя пользователя отображается корректно');
});
});
Этот тест проверяет, что компонент корректно отображает переданное
имя пользователя. Важно, что здесь используется
setupRenderingTest, который помогает настроить окружение
для тестирования рендеринга компонентов.
Сервисы в Ember.js предоставляют возможности для хранения глобальных данных, работы с состоянием приложения или выполнения операций, которые должны быть доступны на протяжении всего жизненного цикла приложения. Unit тестирование сервисов позволяет удостовериться в корректности их работы и функционала.
Пример теста для сервиса:
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Service | auth', function(hooks) {
setupTest(hooks);
test('проверка авторизации пользователя', function(assert) {
let service = this.owner.lookup('service:auth');
service.login('user', 'password');
assert.ok(service.isAuthenticated, 'Пользователь успешно авторизован');
});
});
Здесь тестируется функциональность авторизации, где проверяется, что
после вызова метода login сервис становится
аутентифицированным.
Для тестирования компонентов, сервисов или моделей, которые взаимодействуют с внешними сервисами, часто нужно использовать моки и шпионы. Мокирование позволяет создавать поддельные объекты, которые имитируют поведение реальных зависимостей, а шпионы — отслеживать вызовы функций.
Пример использования шпиона:
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import { spy } from 'sinon';
module('Unit | Service | email', function(hooks) {
setupTest(hooks);
test('отправка email вызывает правильный метод', function(assert) {
let service = this.owner.lookup('service:email');
let sendEmailSpy = spy(service, 'sendEmail');
service.sendEmail('test@example.com', 'Тема', 'Текст письма');
assert.ok(sendEmailSpy.calledOnce, 'Метод sendEmail был вызван');
assert.ok(sendEmailSpy.calledWith('test@example.com', 'Тема', 'Текст письма'), 'Метод вызван с правильными аргументами');
});
});
Здесь используется шпион из библиотеки sinon, чтобы
убедиться, что метод sendEmail был вызван с ожидаемыми
параметрами.
Асинхронные операции — это распространённый сценарий в веб-разработке, и для таких случаев Ember.js предоставляет возможности для работы с промисами и асинхронными действиями.
Пример асинхронного теста:
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import { settled } from '@ember/test-helpers';
module('Unit | Model | post', function(hooks) {
setupTest(hooks);
test('загрузка данных поста из API', async function(assert) {
let store = this.owner.lookup('service:store');
let post = await store.findRecord('post', 1);
assert.equal(post.get('title'), 'Мой первый пост');
});
});
В данном примере используется await для загрузки данных
из API. Тестируется корректность загрузки и правильность данных,
полученных с сервера.
После того как все тесты написаны, их можно запустить с помощью Ember CLI. Для этого достаточно выполнить команду:
ember test
Эта команда запустит все unit тесты, и результаты будут выведены в консоль. Если необходимо запускать тесты в браузере, можно использовать команду:
ember test --serve
Эта команда откроет браузер и покажет результаты тестов в реальном времени.
Тестирование в Ember.js важно для обеспечения качества приложения на всех уровнях. Unit тесты помогают убедиться в правильности работы отдельных частей кода, таких как модели, компоненты и сервисы. Фреймворк Ember предоставляет все необходимые инструменты для тестирования, включая поддержку асинхронных операций, мокирование зависимостей и шпионов. Использование QUnit, интеграция с Ember CLI и настройка тестов позволяют разрабатывать стабильные и надёжные приложения.