Jasmine — это популярная библиотека для тестирования JavaScript, используемая для написания юнит-тестов. С выходом Jasmine 3.x были внесены несколько изменений, улучшений и изменений в API, которые могут потребовать корректировок в уже существующих проектах, использующих версию 2.x. Понимание этих изменений и правильная миграция к новой версии обеспечат стабильную работу тестов и улучшенную производительность тестирования.
beforeEach/afterEach для
асинхронных операций через done()В Jasmine 3.x была введена поддержка асинхронности через
async и await, что позволило отказаться от
использования колбека done() в beforeEach и
afterEach для асинхронных операций. В Jasmine 2.x
использование done() для асинхронных операций в этих хуках
было обязательным, но начиная с версии 3.x это больше не требуется.
Пример старого кода (Jasmine 2.x):
beforeEach(function(done) {
setTimeout(function() {
// Асинхронная операция
done();
}, 1000);
});
Пример кода для Jasmine 3.x:
beforeEach(async () => {
await new Promise(resolve => setTimeout(resolve, 1000));
});
toThrowError с параметром в виде регулярного
выраженияВ Jasmine 3.x был удален устаревший механизм использования регулярных
выражений в toThrowError. Вместо этого рекомендуется
использовать строковое представление ошибки или класс ошибки.
Пример старого кода (Jasmine 2.x):
expect(() => { throw new Error('Test Error') }).toThrowError(/Test/);
Пример кода для Jasmine 3.x:
expect(() => { throw new Error('Test Error') }).toThrowError('Test Error');
spyOnВ Jasmine 3.x появилась возможность работать с объектами, используя
spyOn и проверку на аргументы метода. В версии 2.x не было
поддержки проверки за пределами вызова методов через spyOn,
что значительно улучшилось в версии 3.x. Теперь можно использовать
дополнительные проверки на вызов функций.
Пример старого кода (Jasmine 2.x):
let obj = {
foo: function() {
return 'bar';
}
};
spyOn(obj, 'foo');
obj.foo();
expect(obj.foo).toHaveBeenCalled();
Пример кода для Jasmine 3.x:
let obj = {
foo: function() {
return 'bar';
}
};
spyOn(obj, 'foo').and.callThrough();
obj.foo();
expect(obj.foo).toHaveBeenCalled();
В Jasmine 3.x значительно улучшена работа с таймерами, например, с
функциями setTimeout и setInterval. В новой
версии добавлены дополнительные утилиты, позволяющие более гибко и точно
контролировать асинхронные таймеры в тестах.
Вместо использования jasmine.clock() для манипуляций с
таймерами, теперь можно использовать
jasmine.clock().install() и
jasmine.clock().uninstall(), чтобы правильно управлять
таймерами в тестах.
Пример старого кода (Jasmine 2.x):
beforeEach(function() {
jasmine.clock().install();
});
afterEach(function() {
jasmine.clock().uninstall();
});
it('ждет 1000ms', function() {
setTimeout(function() {
expect(true).toBe(true);
}, 1000);
jasmine.clock().tick(1000);
});
Пример кода для Jasmine 3.x:
beforeEach(function() {
jasmine.clock().install();
});
afterEach(function() {
jasmine.clock().uninstall();
});
it('ждет 1000ms', async function() {
setTimeout(() => {
expect(true).toBe(true);
}, 1000);
jasmine.clock().tick(1000);
});
done() в async/awaitВ Jasmine 3.x появился более современный и удобный способ работы с
асинхронными операциями через async/await. Это
позволяет упростить код, сделать его более читаемым и избавить от
необходимости вручную вызывать done() в тестах.
Пример старого кода (Jasmine 2.x):
it('тестирует асинхронную операцию', function(done) {
someAsyncFunction(function(result) {
expect(result).toBe(true);
done();
});
});
Пример кода для Jasmine 3.x:
it('тестирует асинхронную операцию', async function() {
const result = await someAsyncFunction();
expect(result).toBe(true);
});
fit и xitВ Jasmine 2.x использовались fit и xit для
изолированного тестирования отдельных тестов. В Jasmine 3.x эта практика
остается, но следует помнить, что использование этих методов
ограничивает выполнение других тестов, что может повлиять на результаты
тестирования. Кроме того, fit и xit могут быть
полезными в процессе разработки, но должны быть удалены перед
деплоем.
Jasmine 3.x добавил поддержку Jest-style matcher API, что дает возможность использовать новые возможности для сравнения объектов и структур данных. Это позволяет тестировать более сложные структуры, такие как массивы и объекты, с меньшими усилиями.
Пример старого кода (Jasmine 2.x):
expect({ foo: 'bar' }).toEqual(jasmine.objectContaining({ foo: 'bar' }));
Пример кода для Jasmine 3.x:
expect({ foo: 'bar' }).toEqual(expect.objectContaining({ foo: 'bar' }));
beforeAll и afterAllС выходом Jasmine 3.x также была улучшена поддержка методов
beforeAll и afterAll, которые позволяют
выполнять действия до и после всех тестов в спецификации. Это особенно
полезно для инициализации тестового окружения или очистки ресурсов,
занимающих много времени.
Пример кода для Jasmine 3.x:
beforeAll(async () => {
await setupTestEnvironment();
});
afterAll(async () => {
await cleanupTestEnvironment();
});
it('тестирует что-то', function() {
expect(true).toBe(true);
});
Миграция с Jasmine 2.x на Jasmine 3.x требует внимательного подхода,
особенно в части асинхронных операций и работы с методами
spyOn, таймерами и матчерами. Большая часть изменений
связана с улучшением асинхронной работы и упрощением синтаксиса
тестирования. Понимание этих изменений и их внедрение позволит сделать
тесты более стабильными, читаемыми и эффективными.