Angular2 在单元测试中注入 ElementRef
Angular2 Inject ElementRef in unit test
我正在尝试测试通过 DI 接收对 ElementRef 的引用的组件。
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)
.
要注入 ElementRef:
- 创建模拟
class MockElementRef implements ElementRef {
nativeElement = {};
}
- 为被测组件提供模拟
beforeEachProviders(() => [Component, provide(ElementRef, { useValue: new MockElementRef() })]);
编辑:这是在 rc4 上工作。最终版本引入了重大更改并使此答案无效。
在 Angular 2.2.3:
export class MockElementRef extends ElementRef {}
然后在测试中:
beforeEach(async(() => {
TestBed.configureTestingModule({
providers: [
//more providers
{ provide: ElementRef, useClass: MockElementRef }
]
}).compileComponents();
}));
我在 angular 2.4
中使用来自 @gilad-s 的模拟时遇到 Can't resolve all parameters for ElementRef: (?)
错误
将模拟 class 修改为:
export class MockElementRef extends ElementRef {
constructor() { super(null); }
}
解决测试错误。
在此处阅读 angular 源代码:https://github.com/angular/angular/blob/master/packages/core/testing/src/component_fixture.ts#L17-L60
夹具的 elementRef 不是从模拟注入创建的。并且在正常开发中,我们在向组件注入时不会显式提供 ElementRef
。我认为 TestBed
应该允许相同的行为。
一个好方法是使用 spyOn
和 spyOnProperty
根据需要即时模拟方法和属性。 spyOnProperty
需要 3 个属性,您需要将 get
或 set
作为第三个 属性 传递。 spyOn
适用于 class 和方法以及 returns 所需值。
例子
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);
这里我设置了div.nativeElement
对象的get
of clientWidth
。
我在我的 Angular 项目中更新包后它开始出现。
我尝试了上面的所有解决方案,其中 none 对我有用。当我 运行 npm 运行 test 命令时出现问题。
我设法通过更新所有 jest 依赖项来解决。在这种情况下,我更新的依赖项是@briebug/jest-schematic、@types/jest、jest-preset-angular 和 jest
我正在尝试测试通过 DI 接收对 ElementRef 的引用的组件。
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)
.
要注入 ElementRef:
- 创建模拟
class MockElementRef implements ElementRef {
nativeElement = {};
}
- 为被测组件提供模拟
beforeEachProviders(() => [Component, provide(ElementRef, { useValue: new MockElementRef() })]);
编辑:这是在 rc4 上工作。最终版本引入了重大更改并使此答案无效。
在 Angular 2.2.3:
export class MockElementRef extends ElementRef {}
然后在测试中:
beforeEach(async(() => {
TestBed.configureTestingModule({
providers: [
//more providers
{ provide: ElementRef, useClass: MockElementRef }
]
}).compileComponents();
}));
我在 angular 2.4
中使用来自 @gilad-s 的模拟时遇到Can't resolve all parameters for ElementRef: (?)
错误
将模拟 class 修改为:
export class MockElementRef extends ElementRef {
constructor() { super(null); }
}
解决测试错误。
在此处阅读 angular 源代码:https://github.com/angular/angular/blob/master/packages/core/testing/src/component_fixture.ts#L17-L60
夹具的 elementRef 不是从模拟注入创建的。并且在正常开发中,我们在向组件注入时不会显式提供 ElementRef
。我认为 TestBed
应该允许相同的行为。
一个好方法是使用 spyOn
和 spyOnProperty
根据需要即时模拟方法和属性。 spyOnProperty
需要 3 个属性,您需要将 get
或 set
作为第三个 属性 传递。 spyOn
适用于 class 和方法以及 returns 所需值。
例子
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);
这里我设置了div.nativeElement
对象的get
of clientWidth
。
我在我的 Angular 项目中更新包后它开始出现。
我尝试了上面的所有解决方案,其中 none 对我有用。当我 运行 npm 运行 test 命令时出现问题。
我设法通过更新所有 jest 依赖项来解决。在这种情况下,我更新的依赖项是@briebug/jest-schematic、@types/jest、jest-preset-angular 和 jest