Angular2 Inject ElementRef в unit test
Я пытаюсь протестировать компонент, который получает ссылку на ElementRef через DI.
import { Component, OnInit, ElementRef } from '@angular/core';
@Component({
selector: 'cp',
templateUrl: '...',
styleUrls: ['...']
})
export class MyComponent implements OnInit {
constructor(private elementRef: ElementRef) {
//stuffs
}
ngAfterViewInit() {
// things
}
ngOnInit() {
}
}
и тест:
import {
beforeEach,
beforeEachProviders,
describe,
expect,
it,
inject,
} from '@angular/core/testing';
import { ComponentFixture, TestComponentBuilder } from '@angular/compiler/testing';
import { Component, Renderer, ElementRef } from '@angular/core';
import { By } from '@angular/platform-browser';
describe('Component: My', () => {
let builder: TestComponentBuilder;
beforeEachProviders(() => [MyComponent]);
beforeEach(inject([TestComponentBuilder], function (tcb: TestComponentBuilder) {
builder = tcb;
}));
it('should inject the component', inject([MyComponent],
(component: MyComponent) => {
expect(component).toBeTruthy();
}));
it('should create the component', inject([], () => {
return builder.createAsync(MyComponentTestController)
.then((fixture: ComponentFixture<any>) => {
let query = fixture.debugElement.query(By.directive(MyComponent));
expect(query).toBeTruthy();
expect(query.componentInstance).toBeTruthy();
});
}));
});
@Component({
selector: 'test',
template: '
<cp></cp>
',
directives: [MyComponent]
})
class MyTestController {
}
И компонент, и тестовая схема были созданы Angular-cli. Теперь я не могу выяснить, какого поставщика, если таковой имеется, я должен добавить в beforeEachProviders
чтобы внедрение ElementRef было успешным. Когда я запускаю ng test
я получаю сообщение об Error: No provider for ElementRef! (MyComponent → ElementRef)
Error: No provider for ElementRef! (MyComponent → ElementRef)
.
Ответы
Ответ 1
Вкл Angular 2.2.3:
export class MockElementRef extends ElementRef {}
Тогда в тесте:
beforeEach(async(() => {
TestBed.configureTestingModule({
providers: [
//more providers
{ provide: ElementRef, useClass: MockElementRef }
]
}).compileComponents();
}));
Ответ 2
Я сталкиваюсь Can't resolve all parameters for ElementRef: (?)
Ошибка при использовании макета из @gilad-s в angular 2.4
Модифицированный макет класса:
export class MockElementRef extends ElementRef {
constructor() { super(null); }
}
устраняет ошибку теста
Чтение из углового исходного кода здесь: https://github.com/angular/angular/blob/master/packages/core/testing/src/component_fixture.ts#L17-L60 elementRef светильника не создается из издеваться инъекции. И при обычной разработке мы не предоставляем явно ElementRef
при внедрении в компонент. Я думаю, что TestBed
должен позволять такое же поведение.
Ответ 3
Чтобы ввести ElementRef:
class MockElementRef implements ElementRef {
nativeElement = {};
}
- Предоставить макет тестируемому компоненту
beforeEachProviders(() => [Component, provide(ElementRef, { useValue: new MockElementRef() })]);
EDIT: Это работало на rc4. Заключительный выпуск вносил изменения и аннулировал этот ответ.
Ответ 4
Хорошим способом является использование spyOn
и spyOnProperty
для мгновенного макета методов и свойств по мере необходимости. spyOnProperty
ожидает 3 свойства, и вам нужно передать get
или set
качестве третьего свойства. spyOn
работает с классом и методом и возвращает требуемое значение.
пример
const div = fixture.debugElement.query(By.css('.ellipsis-overflow'));
// now mock properties
spyOnProperty(div.nativeElement, 'clientWidth', 'get').and.returnValue(1400);
spyOnProperty(div.nativeElement, 'scrollWidth', 'get').and.returnValue(2400);
Здесь я устанавливаю get
clientWidth
div.nativeElement
объекта div.nativeElement
.