Angular 2 / 4 - 如何测试指令 @Input 值?

Posted

技术标签:

【中文标题】Angular 2 / 4 - 如何测试指令 @Input 值?【英文标题】:Angular 2 / 4 - How to test Directive @Input values? 【发布时间】:2017-12-30 07:59:03 【问题描述】:

所以我有一个需要输入的指令:

@Directive(
    selector: '[my-directive]'
)
export class MyDirective 

    @Input('some-input')
    public someInput: string;

如您所见,输入应该是string 值。现在,我想为这个指令写一个测试,我想测试输入是否满足string类型:

describe('MyDirective', () => 

    let fixture: ComponentFixture<DummyComponent>;
    let dummy: DummyComponent;
    let directive: DebugElement;

    beforeEach(async(() => 

        TestBed
            .configureTestingModule(
                imports: [
                    MyModule.forRoot()
                ],
                declarations: [
                    DummyComponent
                ]
            )
            .compileComponents();

        fixture = TestBed.createComponent(DummyComponent);
        dummy = fixture.componentInstance;
        directive = fixture.debugElement.query(By.directive(MyDirective));

        fixture.detectChanges();
    ));

    it('should satisfy only a string input and error on other inputs', () => 
        // How to test?
    );
);

@Component(
    selector: 'dummy',
    template: `
        <div my-directive [some-input]="'just-a-string-value'"></div>
    `
)
export class DummyComponent implements OnInit 

如何测试@Input 值是否属于正确类型?

【问题讨论】:

这个link 可能会有所帮助 directive 应该是 DebugElement[] ,要访问这个属性只需 typeof(directives[0].attributes.someInput).toLowerCase() == "string" 【参考方案1】:

所以有点晚了,但我来这里是为了寻找同样的问题,所以我会发布我的解决方案。这是我为测试指令输入(或其他属性)值所做的:

describe('MyDirective', () => 

    let fixture: ComponentFixture<DummyComponent>;
    let dummy: DummyComponent;
    let directive: DebugElement;

    beforeEach(async(() => 

        TestBed
            .configureTestingModule(
                imports: [
                    MyModule.forRoot()
                ],
                declarations: [
                    DummyComponent
                ]
            )
            .compileComponents();

        fixture = TestBed.createComponent(DummyComponent);
        dummy = fixture.componentInstance;
        directive = fixture.debugElement.query(By.directive(MyDirective));

        fixture.detectChanges();
    ));

    it('should satisfy only a string input and error on other inputs', () => 
        
        // needed so template is processed, inputs are updated
        fixture.detectChanges();
        
        // since we declared a ViewChild on the directive, we can access
        // and test directive properties values
        expect(component.directive.someInput).toEqual('just-a-string-value');
        // to test the input type :
        expect(component.directive.someInput).toEqual(Jasmine.any(String));
        // I thought TypeScript would complain when providing a wrong type input to a directive, but no...so I guess I'll test the input type too !
    );
);

@Component(
    selector: 'dummy',
    template: `
        <div my-directive [some-input]="'just-a-string-value'"></div>
    `
)
export class DummyComponent implements OnInit 

  // add a reference to the directive in template
  // so in your component you can access : this.directive, this.directive.someInput
  ViewChild(MyDirective) directive: MyDirective;
所以:修改您的测试组件以保存对指令实例的引用,然后通过 component.directive.[property-name] 访问指令属性。顺便说一句,如果您为指令属性提供默认值(可以通过在模板中提供值来覆盖),您可以在调用 fixture.detectChanges() 之前测试它们。

【讨论】:

以上是关于Angular 2 / 4 - 如何测试指令 @Input 值?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Angular 2 中编译 html?

如何使用输入对 Angular 指令进行单元测试?

Angular2如何对自定义验证器指令进行单元测试?

在 Angular 中使用 Jasmine 使用 *ngIf 指令时,如何对元素是不是可见进行单元测试

是否可以像我们在 Angular 2 中测试属性指令一样对结构指令进行单元测试

Angular 4 - 如何仅在其父级完全渲染后运行指令方法