У меня возникли проблемы с созданием модульного теста для директивы атрибутов Angular, которую я написал. Директива называется TrackClickDirective, и я пытаюсь проверить следующее.
Я подозреваю, что это проблема с моей конфигурацией модульного теста.
Пожалуйста, посмотрите мою реализацию на StackBlitz, где вы можете увидеть выполнение теста:
StackBltiz:https://stackblitz.com/edit/angular-test-click-on-attribute-directive-with-hostlistener
Вот мой код модульного теста — track-click.directive.spec.ts:
import { Component, ElementRef, DebugElement } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from "@angular/platform-browser";
import { TrackClickDirective } from './track-click.directive';
import { Analytics} from './analytics.service';
class MockAnalytics {
eventTrack() {}
};
class MockElementRef {
}
@Component({
template: '<button appTrackClick>Test</button>'
})
export class TestButtonWithoutNameComponent { }
describe('TrackClickDirective', () => {
let component: TestButtonWithoutNameComponent;
let fixture: ComponentFixture<TestButtonWithoutNameComponent>;
let directive: TrackClickDirective;
let inputEl: DebugElement;
let spy: any;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
TestButtonWithoutNameComponent
],
providers: [
TrackClickDirective,
{ provide: Analytics, useClass: MockAnalytics },
{ provide: ElementRef, useClass: MockElementRef }
]
});
fixture = TestBed.createComponent(TestButtonWithoutNameComponent);
component = fixture.componentInstance;
directive = TestBed.get(TrackClickDirective);
inputEl = fixture.debugElement.query(By.css('button'));
});
it('should call the trackClick methoe when the button is clicked', () => {
spy = spyOn(directive, 'trackClick');
inputEl.triggerEventHandler('click', null);
fixture.detectChanges();
expect(directive.trackClick).toHaveBeenCalled();
});
});
Что я здесь делаю неправильно? Когда я запускаю модульный тест, я получаю следующее:
FAILED TESTS:
TrackClickDirective
✖ should call the trackClick method when the button is clicked
HeadlessChrome 72.0.3626 (Mac OS X 10.14.0)
Expected spy trackClick to have been called.
@TheHeadRush - я обновил StackBlitz, чтобы запустить модульный тест, пожалуйста, посмотрите.
Что-то настроено неправильно. Директивы должны быть declarations в TestBed (angular.io/guide/testing#attribute-directive-testing), но я получаю NullInjectorError, когда перемещаю TrackClickDirective из providers в declarations.





По примеру Документы Angular.
Следующее должно помочь:
import { Component, ElementRef, DebugElement } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from "@angular/platform-browser";
import { TrackClickDirective } from './track-click.directive';
import { Analytics} from './analytics.service';
class MockAnalytics {
eventTrack() {}
};
class MockElementRef {
}
@Component({
template: '<button appTrackClick>Test</button>'
})
export class TestButtonWithoutNameComponent { }
describe('TrackClickDirective', () => {
let component: TestButtonWithoutNameComponent;
let fixture: ComponentFixture<TestButtonWithoutNameComponent>;
let directive: TrackClickDirective;
let inputEl: DebugElement;
let spy: any;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
TestButtonWithoutNameComponent,
TrackClickDirective
],
providers: [
TrackClickDirective,
{ provide: Analytics, useClass: MockAnalytics },
{ provide: ElementRef, useClass: MockElementRef }
]
});
fixture = TestBed.createComponent(TestButtonWithoutNameComponent);
component = fixture.componentInstance;
directive = TestBed.get(TrackClickDirective);
inputEl = fixture.debugElement.query(By.css('button'));
});
it('should call the trackClick method when the button is clicked', () => {
directive = fixture.debugElement.query(By.directive(TrackClickDirective)).injector.get(TrackClickDirective) as TrackClickDirective;
spy = spyOn(directive, 'trackClick');
inputEl.triggerEventHandler('click', null);
fixture.detectChanges();
expect(directive.trackClick).toHaveBeenCalled();
});
});
Ключ находится в этой строке:
fixture.debugElement.query(By.directive(TrackClickDirective)).injector.get(TrackClickDirective) as TrackClickDirective;
Несмотря на то, что он очень подробный, он позволяет вам получить фактический экземпляр вашей директивы, который был создан и используется в компоненте, который, в свою очередь, позволяет вам следить за его методами.
Обновленный пример StackBlitz:https://stackblitz.com/edit/angular-test-click-on-attribute-directive-with-hostlistener
Я получаю эту ошибку: TypeError: Cannot read property 'injector' of null. Не могли бы вы заставить ваше решение работать в среде StackBlitz выше?
Оригинальная оболочка StackBlitz кажется сломанной, попробуйте эту: stackblitz.com/edit/angular-wslcvq
Причина, по которой вы получаете эту ошибку, заключается в том, что вам также необходимо включить TrackClickDirective в свои объявления. См. пример стекблиц
Мне не удалось скомпилировать ваш stackblitz для проверки вашего теста, но обычно мне приходится вводить
asyncи оборачивать мои ожидания вfixture.whenStableпри тестировании событий.