【问题标题】:Angular Testing: provide injected @Attribute in TestBedAngular 测试:在 TestBed 中提供注入的 @Attribute
【发布时间】:2018-06-12 12:56:09
【问题描述】:

我有一个通过@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。

【问题讨论】:

    标签: angular testing dependency-injection


    【解决方案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() 对我来说会更好。到目前为止,我看不到任何不利因素。

    【讨论】:

    • 感谢您对包装组件进行测试的建议。至少我可以用这种方法编写测试。
    • 不幸的是,我不能使用@Input,因为我想读取宿主元素的class 属性上提供的类并将它们存储在内部。然后这些类与一组动态的附加类合并,这些附加类反映有关内部状态的附加信息,合并的类集通过覆盖整个类属性的@HostBinding('class') 公开。
    猜你喜欢
    • 1970-01-01
    • 2019-10-24
    • 2018-08-10
    • 2019-05-15
    • 2017-08-17
    • 2017-05-19
    • 1970-01-01
    • 2018-05-21
    • 2016-05-01
    相关资源
    最近更新 更多