Unit testing 角度2单元测试-@ViewChild未定义

Unit testing 角度2单元测试-@ViewChild未定义,unit-testing,angular,angular2-template,ng2-bootstrap,Unit Testing,Angular,Angular2 Template,Ng2 Bootstrap,我正在写一个角度2单元测试。我有一个@ViewChild子组件,我需要在组件初始化后识别它。在本例中,它是ng2引导库中的时间选择器组件,尽管细节不重要。在IdetectChanges()之后,子组件实例仍然未定义 伪代码: @Component({ template: ` <form> <timepicker #timepickerChild [(ngModel)]

我正在写一个角度2单元测试。我有一个
@ViewChild
子组件,我需要在组件初始化后识别它。在本例中,它是ng2引导库中的
时间选择器
组件,尽管细节不重要。在I
detectChanges()之后,子组件实例仍然未定义

伪代码:

@Component({
    template: `
        <form>
            <timepicker
                #timepickerChild
                [(ngModel)]="myDate">
            </timepicker>
        </form>
    `
})
export class ExampleComponent implements OnInit {
    @ViewChild('timepickerChild') timepickerChild: TimepickerComponent;
    public myDate = new Date();
}


// Spec
describe('Example Test', () => {
    let exampleComponent: ExampleComponent;
    let fixture: ComponentFixture<ExampleComponent>;

    beforeEach(() => {
        TestBed.configureTestingModel({
            // ... whatever needs to be configured
        });
        fixture = TestBed.createComponent(ExampleComponent);
    });

    it('should recognize a timepicker'. async(() => {
        fixture.detectChanges();
        const timepickerChild: Timepicker = fixture.componentInstance.timepickerChild;
        console.log('timepickerChild', timepickerChild)
    }));
});
@组件({
模板:`
`
})
导出类ExampleComponent实现OnInit{
@ViewChild('timepickerChild')timepickerChild:TimepickerComponent;
public myDate=新日期();
}
//规格
描述('示例测试',()=>{
让exampleComponent:exampleComponent;
let夹具:组件夹具;
在每个之前(()=>{
TestBed.configureTestingModel({
//…需要配置的任何内容
});
fixture=TestBed.createComponent(例如Component);
});
它('应该识别计时器'.async(()=>{
fixture.detectChanges();
常量timepickerChild:Timepicker=fixture.componentInstance.timepickerChild;
log('timepickerChild',timepickerChild)
}));
});

在到达控制台日志之前,伪代码按预期工作。
timepickerChild
未定义。为什么会发生这种情况?

我认为它应该起作用。可能您忘记在配置中导入某些模块。以下是测试的完整代码:

从'@angular/core/testing'导入{TestBed,ComponentFixture,async};
从'@angular/core'导入{Component,DebugElement};
从'@angular/forms'导入{FormsModule};
从“./test.component”导入{ExampleComponent};
从“ng2引导/ng2引导”导入{TimepickerModule,TimepickerComponent};
描述('示例测试',()=>{
让exampleComponent:exampleComponent;
let夹具:组件夹具;
在每个之前(()=>{
TestBed.configureTestingModule({
导入:[FormsModule,TimepickerModule.forRoot()],
声明:[
示例组件
]
});
fixture=TestBed.createComponent(例如Component);
});
它('应该识别时间选择器'),异步(()=>{
fixture.detectChanges();
常量timepickerChild:TimepickerComponent=fixture.componentInstance.timepickerChild;
log('timepickerChild',timepickerChild);
expect(timepickerChild).tobededefined();
}));
});

在大多数情况下,只需将其添加到声明中即可

beforeEach(async(() => {
        TestBed
            .configureTestingModule({
                imports: [],
                declarations: [TimepickerComponent],
                providers: [],
            })
            .compileComponents() 

确保您的子组件没有计算为false的*ngIf。如果是这样,将导致子组件未定义

如果要使用存根子组件测试主组件,则需要向存根子组件添加提供程序;正如文章中所解释的那样

从'@angular/core'导入{Component};
从“./child.component”导入{ChildComponent};
@组成部分({
选择器:“应用程序子项”,
模板:“”,
供应商:[
{
提供:子组件,
useClass:ChildStubComponent
}
]
})
导出类组件{
updateTimeStamp(){}
}
请注意提供程序元数据,以便在需要ChildComponent时使用类ChildStubComponent


然后,您可以正常创建父组件,其子组件将使用ChildStubComponent类型创建。

即使按照接受的答案中的所有内容进行操作,您仍将获得子组件的未定义实例,请检查该组件是否可见


在我的例子中,控件上应用了
*ngIf
,这就是为什么child的实例没有定义,然后我删除并检查了它,它对我有效

你找到答案了吗?我也有同样的问题。我有一种模糊的感觉,好像大多数选民都有不同的问题。确保您的子组件未被任何
*ngIf=“false”
指令隐藏。另外,在将渲染条件设置为
true
后,执行
fixture.detectChanges()
,这将(重新)创建以前未定义的子组件。我认为这不是一个好的解决方案。如果您在测试中声明组件,那么您对它们有一个硬依赖关系。也就是说,如果他们(出于某种原因)停止工作,你的测试也会失败。如果我想测试主组件而不包括实际的子组件,那么你应该选择模拟组件(比如这里:),那么有没有办法模拟它们呢?@Eugene你能在stackblitz中提供一些例子吗?但是
@ViewChild('timepickerChild')timepickerChild:TimepickerComponent应该是私有字段。非常好,谢谢