Angular2 Inject ElementRef在单元测试中

时间:2016-07-27 20:58:44

标签: unit-testing angular dependency-injection angularjs-e2e

我正在尝试通过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)

4 个答案:

答案 0 :(得分:21)

我遇到Mammal使用角色2.4中的@ gilad-s的模拟错误

将模拟类修改为:

Can't resolve all parameters for ElementRef: (?)

解决了测试错误。

从角度源代码中读取:https://github.com/angular/angular/blob/master/packages/core/testing/src/component_fixture.ts#L17-L60 夹具的elementRef不是从模拟注入创建的。在正常开发中,我们在注入组件时不会明确提供export class MockElementRef extends ElementRef { constructor() { super(null); } } 。我认为ElementRef应该允许相同的行为。

答案 1 :(得分:8)

On Angular 2.2.3:

export class MockElementRef extends ElementRef {}

然后在测试中:

beforeEach(async(() => {
  TestBed.configureTestingModule({
    providers: [
      //more providers
      { provide: ElementRef, useClass: MockElementRef }
    ]
  }).compileComponents();
}));

答案 2 :(得分:7)

注入ElementRef:

  1. 创建模拟
  2. class MockElementRef implements ElementRef {
      nativeElement = {};
    }
    
    1. 将模拟提供给受测试的组件
    2. beforeEachProviders(() => [Component, provide(ElementRef, { useValue: new MockElementRef() })]);
      

      编辑:这是在rc4上工作。最终版本引入了重大更改并使此答案无效。

答案 3 :(得分:1)

一种好方法是使用spyOnspyOnProperty根据需要立即模拟方法和属性。 spyOnProperty需要3个属性,您需要将getset作为第三个属性传递。 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(ngModelChange)。{/ p>