Доступ к настоящему сервису AngularJS в тестах Jasmine при глобальном насмешке - PullRequest
0 голосов
/ 18 декабря 2018

Предположим, у меня есть служба в AngularJS: ComplexService.Он выполняет сложные операции над init и имеет сложный интерфейс ...

В тестах Karma / Jasmine, чтобы упростить модульные тесты других компонентов, я определил макет глобально [1] (вне всех describe объявлений в глобальной области действия Кармы):

beforeEach(function () {
    angular.mock.module('MYMODULE', function ($provide) {
        $provide.value('ComplexService', buildComplexServiceMock());
    });
});

[1] (Причина этого решения состояла в том, чтобы избежать повторного объявления его в каждом наборе тестов- у нас их около 50, и каждый в конечном итоге использует службу косвенно или по умолчанию)

Давайте теперь предположим, что я решил написать какой-то модульный тест для сложной службы.

У меня вопрос: Существует ли способ доступа к реальной услуге сейчас? (не фиктивно)


Мое временное решение - сделать мой сервис доступным и в глобальном масштабе и получить доступэто напрямую:

function ComplexService(Other, Dependencies) {
    //code here
}

angular.module('MYMODULE')
    .service('ComplexService', ['Other', 'Dependencies', ComplexService]);

window.ComplexService = ComplexService;

Но я не доволен этим.(Я не хочу, чтобы производственный код был доступен во всем мире, может быть, кроме как в тестах)

Может кто-нибудь, пожалуйста, подскажите мне?

Редактировать

Еще я быхотелось бы по возможности избегать указания ComplexService зависимостей в тесте напрямую (в случае, если порядок изменится в будущем)

Временное решение, которое плохо :

let complexServiceTestable;

beforeEach(function () {
    inject(function (Other, Dependencies) {
        //If order of dependencies would change, I will have to modify following line:
        complexServiceTestable = window.ComplexService(Other, Dependencies);
    });
});

Что-то, что я был бы признателен больше всего, если это возможно:

let complexServiceTestable;

beforeEach(function () {
    angular.mock.module('MYMODULE', function ($provide) {
        //some magic here
    });
});

beforeEach(function () {
    inject(function (ComplexService) {
        complexServiceTestable = ComplexService;
    });
});

Ответы [ 2 ]

0 голосов
/ 19 декабря 2018

Благодаря подсказкам @MatiasFernandesMartinez в комментариях, после некоторых экспериментов я наконец-то нашел рабочее решение (с использованием провайдера):

В глобальном контексте кармы:

beforeEach(function () {
    angular.mock.module('MYMODULE', function ($provide, ComplexServiceProvider) {
        $provide.value('ComplexServiceBackup', ComplexServiceProvider);
        $provide.value('ComplexService', buildComplexServiceMock());
    });
});

В тестах ComplexService:

describe('ComplexService', function () {
    let complexServiceTestable;

    beforeEach(function () {
        inject(function (ComplexServiceBackup) {
            complexServiceTestable = ComplexServiceBackup.$get();
        });
    });
});
0 голосов
/ 18 декабря 2018

Вы можете сделать это, просто экспортировав реальный service в ваш тест и переопределив реальный макет $ Обеспечить:

import ComplexService from '../your-complex-service-path/ComplexService';

describe('....', function(){

  beforeEach(function () {
    angular.mock.module('MYMODULE', function ($provide) {
        $provide.value('ComplexService', ComplexService);
    });
  });

});

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

...