Угловое тестирование: TestBed не требует предоставления ApplicationRef - PullRequest
0 голосов
/ 04 июля 2018

Я следую официальному руководству по тестированию на https://angular.io/guide/testing написании тестов для приложения.

Поскольку я тестирую сервис с зависимостями, мне нужно предоставить макеты для этих зависимостей, но, что интересно, это не так для ApplicationRef, и мне очень хотелось бы знать, почему.

Сервис примерно такой:

export class MyService {

    constructor(
        private dependentService: DependentService,
        private applicationRef:ApplicationRef
    ){}
    ...

и соответствующая спецификация теста:

describe('MyService', () => {
    let dependentServiceSpy: jasmine.SpyObj<HttpClient>;

    beforeEach(() => {
        const dependentServiceSpy = jasmine.createSpyObj('DependentService', ['test']);

        TestBed.configureTestingModule({
            // Provide both the service-to-test and its (spy) dependency
            // why is 'ApplicationRef' not needed here?? 
            providers: [
                MyService,
                { provide: DependentService, useValue: dependentService_spy }
            ]
        });
    });
    ...   

});

Поскольку и DependentService, и ApplicationRef внедряются в конструктор MyService, я ожидаю, что оба они необходимы в массиве провайдеров TestBed. Но если пропустить 'DependentService', то в тестах выдает ошибку, отсутствующий 'ApplicationRef' не .

Есть ли какое-то разумное объяснение этому?

Ответы [ 3 ]

0 голосов
/ 04 июля 2018

Это возможно потому, что мы вводим ApplicationRef внутрь constructor, не предоставляя его нигде. И это нормально interface, но не provider. Мы предоставляем только providers внутренний тестовый providers массив, а не все, что мы ввели. Это также верно для ChangeDetectorRef. Мы никогда не предоставляем это внутри providers массива.

0 голосов
/ 04 июля 2018

Каждая конфигурация тестирования Angular, использующая TestBed, начинается со следующей инициализации:

getTestBed().initTestEnvironment(
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting()
);

Среда углового тестирования будет использовать BrowserDynamicTestingModule для создания инжектора, как это работает для обычных угловых модулей (см. Также https://blog.angularindepth.com/angular-dependency-injection-and-tree-shakeable-tokens-4588a8f70d5d).

Поставщики угловых слияний, которые BrowserDynamicTestingModule содержат. Этот модуль объявлен следующим образом:

@NgModule({
  exports: [BrowserTestingModule],
  providers: [
    {provide: TestComponentRenderer, useClass: DOMTestComponentRenderer},
  ]
})
export class BrowserDynamicTestingModule {
}

где BrowserTestingModule выглядит так:

                /\
                ||

@NgModule({
  exports: [BrowserModule],
  providers: [
    {provide: APP_ID, useValue: 'a'},
    ELEMENT_PROBE_PROVIDERS,
    {provide: NgZone, useFactory: createNgZone},
  ]
})
export class BrowserTestingModule {
}

и BrowserModule:

                /\
                ||             

@NgModule({providers: BROWSER_MODULE_PROVIDERS, exports: [CommonModule, ApplicationModule]})
export class BrowserModule {
  ...
}

и наконец ApplicationModule объявляет ApplicationRef:

                 /\
                 ||

export const APPLICATION_MODULE_PROVIDERS: StaticProvider[] = [
  {
    provide: ApplicationRef,
    useClass: ApplicationRef,
    deps:
        [NgZone, Console, Injector, ErrorHandler, ComponentFactoryResolver, ApplicationInitStatus]
  },
  ...
];


@NgModule({providers: APPLICATION_MODULE_PROVIDERS})
export class ApplicationModule {
  // Inject ApplicationRef to make it eager...
  constructor(appRef: ApplicationRef) {}
}

и, как вы можете видеть, ApplicationRef провайдер также охотно создается.

Таким образом, здесь нет никакой магии, Angular просто использует тот же алгоритм, как если бы он разрешал провайдеров из пользовательских NgModules

0 голосов
/ 04 июля 2018

Я должен догадаться, но я думаю:

Каждый компонент неявно обнаруживает изменения. Если нет, автоматическое обнаружение изменений не будет работать. Но чтобы использовать эту функциональность в вашем коде напрямую, вы должны явно «перехватить» эту службу в конструкторе.

Теперь наш TestBed создаст те сервисы, которые вы определите там явно. Но он также создаст все эти внутренние необходимые сервисы (например, ChangeDetection, см. Классический «fixture.detectChanges ()»). Поэтому вам не нужно создавать его явно.

Упомянутый вами "DependentService" не является частью внутренней угловой технологии, поэтому вы должны явно указать ее в TestBed.

С уважением

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...