Как выполнить модульное тестирование сервиса / фабрики AngularJS

Я уже некоторое время занимаюсь разработкой с использованием AngularJS, и то, что я пишу, работает, но я знаю, что пришел к точке, где я хотел бы запустить модульные тесты для своего кода AngularJS.

Я создал очень простой сервис, который будет вставлять таблицу стилей на страницу, см. Пример кода ниже:

var OfficeSuiteStylesheetInjectorModule = angular.module('OfficeSuiteStylesheetInjectorModule', []);

OfficeSuiteStylesheetInjectorModule.factory('stylesheetInjectorService', ['$q', function($q) {
    // Returns the service itself.
    return {
        inject: function(id, uri) {
            var deferred = $q.defer();

            // Embed the stylesheet into the page, but only when it's non-existing.
            if (!angular.element('#' + id).length) {
                    var link = StylesheetFactory.Create(id, uri);
                    {
                        link.onload = deferred.resolve;
                        angular.element('head').append(link);
                    }

                    return deferred.promise;
                }
        }
    }
}]);

Это не большой сервис, это просто зависит от $q для обещаний, чтобы я мог запустить дополнительную логику, когда таблица стилей была встроена в страницу.

Теперь я использую Jasmine (я новичок в этом) для тестирования своего кода JavaScript, и я хотел бы протестировать этот модуль.

У меня есть скелет:

// Tests for the angular 'StylesheetInjectorService'.
describe('StylesheetInjectorService', function() {
    var stylesheetInjectorService = {};

    // This code is executed before every test.
    beforeEach(function() {
        // Tells jamine that the module we're working on is the 'OfficeSuiteStylesheetInjectorModule'.
        angular.module('OfficeSuiteStylesheetInjectorModule');
    });

    // Ensures that it injects a stylesheet element into the page.
    it('Should inject a stylesheet element into the page.', function() {
        // How to test here that the stylesheet is injected?
    });
  });
});

Как я могу добавить сервис на страницу и обеспечить загрузку таблицы стилей?

Редактировать: Сервис загрузки теперь работает:

beforeEach(module('OfficeSuiteStylesheetInjectorModule'));

// This code is executed before every test.
beforeEach(function() {

    // Inject the required dependencies into the page.
    inject(function($injector) {
        stylesheetInjectorService = $injector.get('stylesheetInjectorService');
    });
});

Однако тот же вопрос остается открытым. Как проверить, была ли таблица стилей встроена в страницу?

Любая помощь высоко ценится.

С уважением

2 ответа

Решение

Написать спецификацию для прикрепления таблицы стилей к angular.element('head') Я бы немного изменил логику, чтобы привязать его к $document.head,

Если вы не хотите этого делать, я бы порекомендовал вам изменить свой сервис на directive видя, как внедрение элемента сценария, манипулирование DOM. Таким образом, вы убили бы двух зайцев одним выстрелом $compile проверить вашу директиву (которая позволит вам скомпилировать head элемент для загрузки). Но пока это немного "сверх".

Реализация:

if (!angular.element('#' + id).length) {
  var link = StylesheetFactory.Create(id, uri);

    link.onload = deferred.resolve;

    $document.head.append(link);

    return deferred.promise;
  }
}

beforeEach:

/**
 * Sorry, this was previously $location which was just 
 * such a silly mistake.
 */
var $timeout; 

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

Это:

it('attaches the stylesheet to $document.head', function () {
  styleSheetInjectorService.inject('someId', '/path/to/some/stylesheet');
  $timeout.flush(); // flush promises
  expect(angular.element($document.head).lastChild[0].nodeName).to.eq('LINK');
});

Что-то в этом роде должно заставить вас работать. Не забывайте, что в спецификации, которую я написал, используются утверждения стиля chai # автомата и тестовый фреймворк mocha. Измените синтаксис, чтобы он соответствовал Jasmine, если вы хотите скопировать и вставить.

У меня было это сомнение некоторое время назад. Чтобы внедрить ваши контроллеры и сервисы в ваши тесты, вам нужно использовать инструмент под названием Angular Mocks. Вот официальное упоминание об этом.

Я полагаю, вы используете его вместе со средой Кармы.

Вот отличное руководство по началу работы:

https://www.airpair.com/angularjs/posts/unit-testing-angularjs-applications

Этот другой предназначен для Ionic Framework, но все еще может применяться в вашем случае

Надеюсь, это поможет.

Другие вопросы по тегам