角度测试:在TestBed中提供注入的@Attribute

时间:2018-06-12 12:56:09

标签: angular testing dependency-injection

我有一个组件可以通过@Attribute注入一个属性:

@Component({
  selector: 'app-foo',
  templateUrl: './foo.component.html'
})
export class FooComponent implements OnInit {

  constructor(@Attribute('foo') private foo: string) {
    // do something with foo
  }
}

现在我想用Jasmine和Karma编写测试。遗憾的是,我无法通过TestBed进样器找到有关如何在测试中提供此属性的任何文档。

这就是我的尝试:

describe('FooComponent', () => {

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      providers: [
        {provide: 'foo', useValue: 'bar'},
        {provide: Attribute('foo'), useValue: 'bar'},
      ],
      declarations: [FooComponent],
    })
      .compileComponents();
  }));

  it('should merge outer class', () => {
    const fixture = TestBed.createComponent(FooComponent);
    const component = fixture.componentInstance;
    fixture.detectChanges();

    // do actual testing
  });
});

经过一些研究后,我还定义了以下内容,但没有成功:

Inject('foo')(FooComponent, null, 0);
Attribute('foo')(FooComponent, null, 0);

传递给构造函数的参数始终为null。有人知道解决方案吗?我使用的是Angular 5.2.10。

1 个答案:

答案 0 :(得分:1)

还要努力提供@Attribute()装饰器替代。

作为解决方法,您可以将构造函数中的@Attribute()更改为组件类上的@Input() foo: string;。或使用包装器组件,然后在包装器组件上设置属性,如下所示:

import { TestBed } from "@angular/core/testing";
import { Attribute, Component } from "@angular/core";
import { By } from "@angular/platform-browser";

describe('FooComponent', () => {
  it('should allow you to use attribute decorator', () => {
    TestBed.configureTestingModule({
      declarations: [FooComponent, WrapperComponent],
    });

    const wrapperFixture = TestBed.createComponent(WrapperComponent);
    wrapperFixture.detectChanges();

    const fooComponent = wrapperFixture.debugElement.query(By.directive(FooComponent)).componentInstance;
    expect(fooComponent.bar).toEqual('baz');
  });
});

@Component({
  selector: "foo-component",
  template: "<p>Foo works: {{bar}}</p>",
})
class FooComponent {
  bar: '';
  constructor(@Attribute('foo') private foo: string) {
    this.bar = foo;
  }
}

@Component({
  selector: "wrapper-component",
  template: "<foo-component foo='baz'></foo-component>"
})
class WrapperComponent {
}

我认为在组件上使用@Input()对我来说会更好。到目前为止,我看不到任何不利之处。