В Jasmine существует мощный механизм для расширения стандартного набора матчеров с помощью custom matchers. Это позволяет создавать свои методы проверки, которые делают тесты более читаемыми и выразительными, а также позволяют сократить дублирование кода при сложных проверках.
Custom matcher — это функция, которая возвращает объект с ключом
compare. В этом объекте описывается логика проверки
значения и возвращается результат в виде объекта с полями:
pass — булево значение, показывающее, прошла ли
проверка;message — строка с пояснением, которая выводится при
неудачном тесте.Простейший пример:
beforeEach(function() {
jasmine.addMatchers({
toBeEven: function() {
return {
compare: function(actual) {
const result = {};
result.pass = actual % 2 === 0;
result.message = result.pass
? `Ожидалось, что ${actual} не будет чётным`
: `Ожидалось, что ${actual} будет чётным`;
return result;
}
};
}
});
});
describe('Пример custom matcher', function() {
it('проверяет чётность числа', function() {
expect(4).toBeEven();
expect(5).not.toBeEven();
});
});
Здесь ключевое:
jasmine.addMatchers регистрирует matcher глобально для
текущего набора тестов;compare получает фактическое
значение (actual) и, при необходимости,
дополнительные аргументы;pass и message позволяет
Jasmine корректно отобразить результат.Custom matcher может принимать дополнительные параметры. Например, проверка, что число находится в диапазоне:
beforeEach(function() {
jasmine.addMatchers({
toBeWithinRange: function() {
return {
compare: function(actual, floor, ceiling) {
const result = {};
result.pass = actual >= floor && actual <= ceiling;
result.message = result.pass
? `Ожидалось, что ${actual} не находится в диапазоне от ${floor} до ${ceiling}`
: `Ожидалось, что ${actual} находится в диапазоне от ${floor} до ${ceiling}`;
return result;
}
};
}
});
});
describe('Проверка числа в диапазоне', function() {
it('число находится между 5 и 10', function() {
expect(7).toBeWithinRange(5, 10);
expect(12).not.toBeWithinRange(5, 10);
});
});
Аргументы после actual передаются в matcher через
expect(value).matcher(arg1, arg2).
Jasmine поддерживает работу с промисами и асинхронными функциями.
Custom matcher можно интегрировать с async/await, если
внутренняя логика зависит от асинхронного вызова. Важно возвращать
результат синхронно, а асинхронную работу обрабатывать
заранее:
beforeEach(function() {
jasmine.addMatchers({
toResolveWithValue: function() {
return {
compare: async function(actualPromise, expected) {
const result = {};
try {
const value = await actualPromise;
result.pass = value === expected;
result.message = result.pass
? `Ожидалось, что промис не вернёт ${expected}`
: `Ожидалось, что промис вернёт ${expected}, но вернул ${value}`;
} catch (err) {
result.pass = false;
result.message = `Промис завершился с ошибкой: ${err}`;
}
return result;
}
};
}
});
});
describe('Асинхронный custom matcher', function() {
it('проверяет результат промиса', async function() {
const promise = Promise.resolve(42);
await expectAsync(promise).toResolveWithValue(42);
});
});
Для асинхронных матчеров используется expectAsync, и
matcher должен корректно обрабатывать промис.
Custom matchers можно организовать в отдельные модули для повторного
использования. Например, создать файл matchers.js:
export const numericMatchers = {
toBeEven: function() { /* реализация */ },
toBeWithinRange: function() { /* реализация */ }
};
И подключать в тестах:
import { numericMatchers } from './matchers';
beforeEach(function() {
jasmine.addMatchers(numericMatchers);
});
Это улучшает читаемость кода и поддерживаемость крупных проектов.
not — логика должна
корректно работать как при положительном, так и при отрицательном
вызове.Jasmine позволяет использовать дополнительные поля в объекте
compare:
negativeCompare — можно отдельно определить поведение
для expect(...).not.toMatcher(). В большинстве случаев
достаточно писать только compare, так как Jasmine
автоматически инвертирует pass.customMessage — можно формировать более сложные
динамические сообщения, используя значения аргументов и фактического
результата.Создание кастомных матчеров — один из ключевых инструментов для повышения выразительности тестов в Jasmine. Они помогают сделать проверки более читаемыми, модульными и адаптированными к специфике проекта.