Named exports в JavaScript позволяют экспортировать несколько объектов, функций или переменных из одного модуля. В отличие от default exports, где может быть экспортирован только один элемент, named exports позволяют экспортировать несколько элементов с их именами. При тестировании таких экспортах важно правильно имплементировать моки и проверку в Jasmine, чтобы изолировать логику и обеспечить корректность выполнения кода.
Модуль с named exports может выглядеть следующим образом:
// math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
export const multiply = (a, b) => a * b;
Здесь экспортируются три функции, каждая из которых доступна по своему имени в других модулях. Для импорта таких функций в другом файле используется синтаксис:
import { add, subtract, multiply } from './math';
Важно понимать, что каждый из этих объектов или функций доступен по имени, что позволяет легко изолировать тесты и работать с модулями независимо друг от друга.
Для корректного тестирования named exports необходимо убедиться, что
Jasmine правильно имитирует импорты. В тестах можно использовать функции
spyOn и моки, чтобы подменять или проверять вызовы
функций.
Предположим, что нам нужно протестировать файл, который зависит от
функции add из модуля math.js. Тестируемая
функция выглядит следующим образом:
// calculator.js
import { add, subtract } from './math';
export const calculateSum = (a, b) => add(a, b);
Тестирование данной функции требует того, чтобы Jasmine мог
мокировать функцию add для проверки работы функции
calculateSum.
Jasmine предоставляет методы для мокирования зависимостей, такие как
spyOn и jest.fn(). Для примера с
calculateSum мы можем использовать spyOn:
// calculator.spec.js
import * as math from './math';
import { calculateSum } from './calculator';
describe('calculator', () => {
it('should call add function', () => {
spyOn(math, 'add').and.returnValue(10); // Мокаем функцию add
const result = calculateSum(5, 5);
expect(math.add).toHaveBeenCalledWith(5, 5); // Проверяем, что add был вызван с правильными аргументами
expect(result).toBe(10); // Проверяем результат
});
});
Здесь функция spyOn подменяет реальную функцию
add, обеспечивая возврат заранее заданного значения (в
данном случае 10). Важно, что проверка
expect(math.add).toHaveBeenCalledWith(5, 5) позволяет
удостовериться, что функция была вызвана с правильными аргументами.
Named exports могут также включать асинхронные функции. Рассмотрим пример:
// api.js
export const fetchData = async (url) => {
const response = await fetch(url);
const data = await response.json();
return data;
};
Для тестирования асинхронных функций важно использовать Jasmine
функции для работы с промисами, такие как done или
async/await. Пример теста для fetchData может
выглядеть так:
// api.spec.js
import * as api from './api';
describe('fetchData', () => {
it('should fetch data from API', async () => {
const mockResponse = { id: 1, name: 'John Doe' };
spyOn(global, 'fetch').and.returnValue(Promise.resolve({
json: () => Promise.resolve(mockResponse),
}));
const result = await api.fetchData('https://api.example.com/user/1');
expect(fetch).toHaveBeenCalledWith('https://api.example.com/user/1');
expect(result).toEqual(mockResponse);
});
});
В этом примере используется spyOn для подмены глобальной
функции fetch, чтобы возвратить фейковый ответ. Метод
await позволяет дождаться выполнения асинхронной функции
перед проверкой результатов.
Использование spyOn для проверки
вызовов. Если нужно проверить, сколько раз и с какими
аргументами была вызвана функция, используйте spyOn для
отслеживания вызова.
Подмена возвращаемых значений. Метод
and.returnValue() позволяет моку возвращать заранее
заданное значение, что полезно при тестировании сложных
зависимостей.
Тестирование сторонних зависимостей. В случае работы с внешними сервисами, например, API-запросами, используйте моки для подмены этих сервисов, чтобы изолировать тестируемую логику.
Тестирование исключений. Важно проверять, что
функции корректно обрабатывают ошибки. Для этого можно использовать
and.throwError() в моке.
Асинхронные тесты. В случае работы с
асинхронными функциями важно использовать async/await или
done для того, чтобы тесты корректно ожидали завершения
выполнения асинхронных операций.
Когда модуль экспортирует несколько элементов, как это часто бывает в
утилитных библиотеках, важно изолировать тестирование каждого экспорта.
Например, если файл utils.js экспортирует несколько
функций:
// utils.js
export const formatDate = (date) => {
const d = new Date(date);
return `${d.getDate()}/${d.getMonth() + 1}/${d.getFullYear()}`;
};
export const capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);
Тестирование этих функций будет включать импорт каждого экспорта по имени и мокацию при необходимости:
// utils.spec.js
import * as utils from './utils';
describe('utils', () => {
it('should format date correctly', () => {
const date = '2021-05-01';
const formattedDate = utils.formatDate(date);
expect(formattedDate).toBe('1/5/2021');
});
it('should capitalize the string', () => {
const str = 'hello';
const capitalizedStr = utils.capitalize(str);
expect(capitalizedStr).toBe('Hello');
});
});
В этом примере тестируются две независимые функции. Каждая из них проверяется на корректность выполнения своей задачи.
Если модули используют внешние библиотеки, такие как
axios или lodash, их тоже можно мокирать с
помощью Jasmine. Например, для библиотеки axios можно
мокировать функции get, post и другие, чтобы
изолировать тестируемую логику.
import axios from 'axios';
import * as api from './api';
describe('api', () => {
it('should fetch data correctly', async () => {
spyOn(axios, 'get').and.returnValue(Promise.resolve({ data: { id: 1, name: 'Test' } }));
const result = await api.fetchData('https://api.example.com/user/1');
expect(result).toEqual({ id: 1, name: 'Test' });
});
});
Мокирование внешних библиотек позволяет тестировать логику, не зависимую от реальных внешних сервисов, что делает тесты быстрыми и независимыми.
Тестирование named exports в Jasmine требует внимательности к деталям
при мокировании зависимостей и правильной настройке окружения.
Использование spyOn, моков и асинхронных тестов позволяет
точно проверять работу функций, зависимых от внешних библиотек и других
модулей.