Постоянство сервисного элемента модульного тестирования Angular

В настоящее время я пишу службу для управления потоком загрузки. Сейчас я пишу модульные тесты для функции, которая показывает и скрывает модальное окно загрузки. В тестах я использую angular.element.find, чтобы проверить, существует ли модальное окно. Во втором тесте число увеличивается по сравнению с тем, что я ожидал, как будто оно не сбрасывается.

Два теста заключаются в следующем:

    describe('show', function() {
        it('should initially not show the modal', function() {
            expect(upload.isShowing()).toEqual(false);
            expect(angular.element.find('.modal').length).toEqual(0);
        });

        it('should show the upload modal', function() {
            expect(upload.isShowing()).toEqual(false);
            expect(angular.element.find('.modal').length).toEqual(0);

            upload.show();
            $rootScope.$digest();
            expect(upload.isShowing()).toEqual(true);
            expect(angular.element.find('.modal').length).toEqual(1);
        });
    });

    describe('cancel', function() {
        it('should hide the upload form', function() {
            expect(upload.isShowing()).toEqual(false);
            expect(angular.element.find('.modal').length).toEqual(0);

            upload.show();
            $rootScope.$digest();
            expect(upload.isShowing()).toEqual(true);
            expect(angular.element.find('.modal').length).toEqual(1);

        });
    });

Первый блок description проходит нормально, а вот второй терпит неудачу. Он говорит мне, что это Expected 1 to equal 0. Если я закомментирую первое ожидание с помощью angular.element.find в тесте для cancel, он скажет: «Ожидается, что 2 будет равно 1».

Все, что я могу определить, это то, что весь HTML-код помещается в одно и то же пространство и усугубляется после каждого теста. Есть ли способ предотвратить такое поведение или использовать оператор afterEach для сброса предыдущего HTML?

Спасибо!


Поправка

Вот полный код для этого набора тестов, если это поможет:

describe('uploadService', function() {
    var $rootScope,
        upload;

    beforeEach(module('upload'));
    beforeEach(module('upload.service'));
    beforeEach(module('bublNg.templates'));
    beforeEach(module('ui.bootstrap.tpls'));

    beforeEach(inject(function($injector) {
        upload = $injector.get('upload');
        $rootScope = $injector.get('$rootScope');
    }));

    describe('isShowing', function() {
        it('should return true if the modal us showing', function() {
            expect(upload.isShowing()).toEqual(false);

            upload.show();
            expect(upload.isShowing()).toEqual(true);
        });
    });

    describe('show', function() {
        it('should initially not show the modal', function() {
            expect(upload.isShowing()).toEqual(false);
            expect(angular.element.find('.modal').length).toEqual(0);
        });

        it('should show the upload modal', function() {
            expect(upload.isShowing()).toEqual(false);
            expect(angular.element.find('.modal').length).toEqual(0);

            upload.show();
            $rootScope.$digest();
            expect(upload.isShowing()).toEqual(true);
            expect(angular.element.find('.modal').length).toEqual(1);
        });
    });

    describe('cancel', function() {
        it('should hide the upload form', function() {
            expect(upload.isShowing()).toEqual(false);
            // expect(angular.element.find('.modal').length).toEqual(0);

            upload.show();
            $rootScope.$digest();
            expect(upload.isShowing()).toEqual(true);
            // expect(angular.element.find('.modal').length).toEqual(1);
            upload.cancel();
            expect(upload.isShowing()).toEqual(false);

        });
    });
});

person Octothorpe    schedule 10.12.2014    source источник


Ответы (2)


Избегайте проверки присутствия элемента html для чего-то подобного. Поскольку вы используете UI Bootstrap, вы должны внедрить сервис $modal в свои тесты и следить за его методом open. Затем проверьте вызовы вашего кода. Это предотвращает загрязнение DOM во время ваших тестов.

Этот шаблон должен помочь вам начать:

var $modal;

beforeEach(inject(function($injector) {
    $modal = $injector.get('$modal');
}));

beforeEach(function() {
    spyOn($modal, 'open');
    // or, to mock/fake a modal object so you can test close/dismiss handlers
    // spyOn($modal, 'open').and.returnValue(mockModal);
    // see: http://stackoverflow.com/a/21370703/2943490
});

describe('show', function() {
    it('should initially not show the modal', function() {
        expect($modal.open).not.toHaveBeenCalled();
    });

    it('should show the upload modal', function() {
        upload.show();
        $rootScope.$digest();

        expect($modal.open).toHaveBeenCalledWith({
            // your modal options
        });
    });
});
person user2943490    schedule 11.12.2014
comment
Спасибо! Хороший подход, однозначно. Я не думал о том, чтобы шпионить за самой модальной службой, но это имеет смысл. Я перейду на этот метод. Из любопытства, вы хоть представляете, почему я добивался таких результатов? Есть ли что-то, что не очищается между тестами? - person Octothorpe; 11.12.2014
comment
@Octothorpe, ваше первое наблюдение было правильным: все, что я могу определить, это то, что весь html попадает в одно и то же пространство и суммируется после каждого теста. Вы можете частично обойти это, выполнив поиск в DOM .modal в afterEach и удалив его, но вам не придется беспокоиться об этом, шпионя за $modal.open. Также обратите внимание, что $modal ведет внутренний реестр открытых модальных окон, поэтому простое удаление их из DOM на самом деле не приводит к очистке. - person user2943490; 12.12.2014
comment
Хорошо, круто, приятно знать. Мне еще многое предстоит узнать о том, что происходит под капотом во многом из этого. Спасибо за подтверждение! - person Octothorpe; 12.12.2014

Прямо сейчас вы, вероятно, разместили код для настройки вашего теста в начале вашего файла. Вместо этого попробуйте поместить его в оператор beforeEach.

person ngstschr    schedule 10.12.2014
comment
Просто добавил полный код для модульного теста. Дайте мне знать, если это может помочь прояснить что-либо. Я не уверен на 100%, что вы имеете в виду. - person Octothorpe; 11.12.2014