модульные тесты для компонента с использованием служебного класса со статическими методами - PullRequest
0 голосов
/ 24 мая 2018

У меня есть компонент, который использует класс LocaleService и статический метод этого сервиса instant().LocaleService в не впрыскивается в компонент.Во время тестирования компонента меня не интересуют LocaleService внутренние компоненты, и я не хочу его тестировать.Таким образом, в beforeEach я добавил шпиона

const localeServiceInstantSpy = spyOn(LocaleService, 'instant');
localeServiceInstantSpy.and.callFake(msg => msg);

Это хорошо работает.Теперь мне нужно переместить этого шпиона (и других) в заглушку LocaleService и использовать ее в этом тесте и тестах других компонентов с использованием LocaleService - их много.Какой самый правильный способ достичь этого?Как создать повторно используемый LocaleServiceStub?

\app\utils\locale.service.ts

export class LocaleService {

    public static lang: string;

    private static messages = {
        'user.add': {
            en: 'Add Local User Account',
            de: 'Add Local User Account DE'
        },
        'user.edit': {
            en: 'Edit Local User Account',
            de: 'Edit Local User Account DE'
        }
    };

    public static instant(key: string) {
        return this.messages[key][this.lang];
    }

}

Использование в тестируемом классе \app\settings\users\user-form.component.ts

import { LocaleService } from 'app/utils/locale.service';
...
getDialogHeader() {
    return this.isNewUser ? LocaleService.instant('user.add') : LocaleService.instant('user.edit');
}
...

1 Ответ

0 голосов
/ 25 мая 2018

Статические классы имеют запах кода в JavaScript.Если класс никогда не создается, то в этом нет необходимости.

Это один из случаев, к которым должен обращаться Angular DI.Он должен быть реорганизован в сервис, а не в класс, который используется напрямую.

class LocaleService {
    public lang: string;

    private messages = {...};

    public instant(key: string) {
        return this.messages[key][this.lang];
    }
}

...
providers: [LocaleService, ...]
...

Затем его можно сменить с помощью DI.Для повторного использования макет может быть определен как провайдер:

const LOCALE_SERVICE_MOCK = {
  provide: LocaleService,
  useFactory: () => ({
    instant: jasmine.createSpy('instant').and.callFake(msg => msg)
  })
};

и указываться в тестовом стенде:

beforeEach(() => {
  TestBed.configureTestingModule({ providers: [LOCALE_SERVICE_MOCK]});
});

или быть завернутым в модуль:

beforeEach(() => {
  TestBed.configureTestingModule({ imports: [LocaleServiceMockModule]});
});

В своем текущем состоянии код можно сделать DRYer, переместив код многократного использования в функцию:

function mockLocaleService() {
  const localeServiceInstantSpy = spyOn(LocaleService, 'instant');
  localeServiceInstantSpy.and.callFake(msg => msg);
}

И используя его при необходимости:

beforeEach(mockLocaleService);
...