У меня есть угловая служба requestNotificationChannel
:
app.factory("requestNotificationChannel", function($rootScope) {
var _DELETE_MESSAGE_ = "_DELETE_MESSAGE_";
function deleteMessage(id, index) {
$rootScope.$broadcast(_DELETE_MESSAGE_, { id: id, index: index });
};
return {
deleteMessage: deleteMessage
};
});
Я пытаюсь выполнить модульное тестирование этой службы с помощью жасмина:
"use strict";
describe("Request Notification Channel", function() {
var requestNotificationChannel, rootScope, scope;
beforeEach(function(_requestNotificationChannel_) {
module("messageAppModule");
inject(function($injector, _requestNotificationChannel_) {
rootScope = $injector.get("$rootScope");
scope = rootScope.$new();
requestNotificationChannel = _requestNotificationChannel_;
})
spyOn(rootScope, '$broadcast');
});
it("should broadcast delete message notification", function(done) {
requestNotificationChannel.deleteMessage(1, 4);
expect(rootScope.$broadcast).toHaveBeenCalledWith("_DELETE_MESSAGE_", { id: 1, index: 4 });
done();
});
});
Я читал об асинхронной поддержке в Jasmine, но, поскольку я новичок в модульном тестировании с помощью javascript, не смог заставить его работать.
Я получаю сообщение об ошибке:
Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL
и мой тест занимает слишком много времени (около 5 с).
Может ли кто-нибудь помочь мне предоставить рабочий пример моего кода с некоторыми пояснениями?
Jest
ожидалось - очень часто при отладке и необходимости времени для проверки переменных.afterEach
шаг, который очищает базу данных (используяdeleteMany
метод). Добавлениеjest.setTimeout(30000);
вbeforeAll
методе , похоже, закрепился это для меня - я предполагаю , так как удаление базы данных является сетевым вызовом (в состоянии), это иногда занимает больше времени , чем на 3 секунды и метание.Ответы:
Наличие аргумента в вашей
it
функции (done
в приведенном ниже коде) заставит Jasmine попытаться выполнить асинхронный вызов.//this block signature will trigger async behavior. it("should work", function(done){ //... }); //this block signature will run synchronously it("should work", function(){ //... });
Не имеет значения, как назван
done
аргумент, важно только его существование. Я столкнулся с этой проблемой из-за слишком большого количества копий / пасты.В документации Jasmine Asynchronous Support отмечается, что аргумент (названный
done
выше) - это обратный вызов, который можно вызвать, чтобы сообщить Jasmine, когда асинхронная функция завершена. Если вы никогда не позвоните, Жасмин никогда не узнает, что ваш тест завершен, и в конечном итоге у него истечет время ожидания.источник
Даже для асинхронных тестов в этих случаях срабатывает тайм-аут. Вы можете обойти эту ошибку, увеличив значение лимита тайм-аута для оценки асинхронного обратного вызова Jasmine.
describe('Helper', function () { var originalTimeout; beforeEach(function() { originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000000; }); afterEach(function() { jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout; }); it('Template advance', function(doneFn) { $.ajax({ url: 'public/your-end-point.mock.json', dataType: 'json', success: function (data, response) { // Here your expected using data expect(1).toBe(1) doneFn(); }, error: function (data, response) { // Here your expected using data expect(1).toBe(1) doneFn(); } }); }); });
Источник: http://jasmine.github.io/2.0/introduction.html#section-42
источник
Эта ошибка также может быть вызвана отсутствием инъекции при инициализации службы / фабрики или чего-то еще. Например, его можно бросить так:
var service; beforeEach(function(_TestService_) { service = _TestService_; });
Чтобы исправить это, просто оберните функцию с помощью inject, чтобы правильно получить службу:
var service; beforeEach(inject(function(_TestService_) { service = _TestService_; }));
источник
import { fakeAsync, ComponentFixture, TestBed } from '@angular/core/testing';
использовать fakeAsync
beforeEach(fakeAsync (() => { //your code })); describe('Intilalize', () => { it('should have a defined component', fakeAsync(() => { createComponent(); expect(_AddComponent.ngOnInit).toBeDefined(); })); });
источник
Вы можете использовать плагин karma-jasmine для глобальной установки интервала тайм-аута по умолчанию.
Добавьте этот конфиг в karma.conf.js
module.exports = function(config) { config.set({ client: { jasmine: { timeoutInterval: 10000 } } }) }
источник
Эта ошибка началась для меня совершенно неожиданно, на тесте, который всегда работал. Я не мог найти никаких предложений, которые помогли бы, пока не заметил, что мой Macbook работает медленно. Я заметил, что процессор был привязан к другому процессу, который я убил. Ошибка асинхронности Jasmine исчезла, и мои тесты снова в порядке.
Не спрашивайте меня почему, я не знаю. Но в моих обстоятельствах, казалось, виновата нехватка системных ресурсов.
источник
Это скорее наблюдение, чем ответ, но оно может помочь другим, которые были так же разочарованы, как и я.
Я продолжал получать эту ошибку из двух тестов в моем наборе. Я думал, что просто сломал тесты с помощью рефакторинга, который я делал, поэтому после того, как откат изменений не сработал, я дважды (две версии назад) вернулся к более раннему коду, думая, что это избавит от ошибки. Это ничего не изменило. Я гнался за своим хвостом вчера весь день и часть утра, не решив проблему.
Я расстроился и проверил код на ноутбуке сегодня утром. Прогнал весь набор тестов (около 180 тестов), ошибок нет. Так что ошибок никогда не было в коде или тестах. Вернулся в свой ящик разработчика и перезагрузил его, чтобы очистить все в памяти, что могло вызвать проблему. Без изменений, одинаковые ошибки в тех же двух тестах. Поэтому я удалил каталог со своей машины и снова проверил его. Вуаля! Ошибок нет.
Не знаю, что это вызвало или как это исправить, но удаление рабочего каталога и его возврат исправили, что бы это ни было.
Надеюсь, это кому-то поможет.
источник
Вы также получаете эту ошибку, когда ожидаете чего-то в
beforeAll
функции!describe('...', function () { beforeAll(function () { ... expect(element(by.css('[id="title"]')).isDisplayed()).toBe(true); }); it('should successfully ...', function () { } }
источник
Не используйте
done
, просто оставьте вызов функции пустым.источник
В моем случае эта ошибка была вызвана неправильным использованием fixture.detectChanges (). Кажется, этот метод является прослушивателем событий (асинхронным), который будет отвечать на обратный вызов только при обнаружении изменений. Если никаких изменений не обнаружено, он не вызовет обратный вызов, что приведет к ошибке тайм-аута. Надеюсь это поможет :)
источник
Работает после удаления
scope
ссылки и аргументов функции:"use strict"; describe("Request Notification Channel", function() { var requestNotificationChannel, rootScope; beforeEach(function() { module("messageAppModule"); inject(function($injector, _requestNotificationChannel_) { rootScope = $injector.get("$rootScope"); requestNotificationChannel = _requestNotificationChannel_; }) spyOn(rootScope, "$broadcast"); }); it("should broadcast delete message notification with provided params", function() { requestNotificationChannel.deleteMessage(1, 4); expect(rootScope.$broadcast).toHaveBeenCalledWith("_DELETE_MESSAGE_", { id: 1, index: 4} ); }); });
источник
// this block signature will trigger async behavior. it("should work", function(done){ // do stuff and then call done... done(); }); // this block signature will run synchronously it("should work", function(){ //... });
источник
жасмин.DEFAULT_TIMEOUT_INTERVAL = 100000;
Сохранение этого в блоке решило мою проблему.
it('', () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000; });
источник
Что я сделал: добавил / обновил следующий код:
framework: 'jasmine', jasmineNodeOpts: { // Jasmine default timeout defaultTimeoutInterval: 60000, expectationResultHandler(passed, assertion) { // do something }, }
источник
Вместо того
beforeEach(() => {..
использовать
beforeEach(fakeAsync(() => {..
источник
Похоже, что тест ждет некоего обратного вызова, которого так и не произошло. Вероятно, потому что тест не выполняется с асинхронным поведением.
Во-первых, посмотрите, не используется ли просто fakeAsync в вашем «его» сценарии:
it('should do something', fakeAsync(() => {
Вы также можете использовать
flush()
для ожидания завершения очереди микрозадач илиtick()
для ожидания определенного количества времени.источник
Если у вас есть аргумент (
done
) вit
функции, попробуйте удалить его, а также его вызов внутри самой функции:it("should broadcast delete message notification", function(/*done -> YOU SHOULD REMOVE IT */) { requestNotificationChannel.deleteMessage(1, 4); expect(rootScope.$broadcast).toHaveBeenCalledWith("_DELETE_MESSAGE_", { id: 1, index: 4 }); // done(); -> YOU SHOULD REMOVE IT });
источник