使用模拟服务时在业力测试中调用 OnInit() 后组件未定义

Posted

技术标签:

【中文标题】使用模拟服务时在业力测试中调用 OnInit() 后组件未定义【英文标题】:component undefined after calling OnInit() in karma test when using mock services 【发布时间】:2018-01-30 13:59:56 【问题描述】:

我正在编写一个单元测试来测试角度组件上的 OnInit 钩子。它调用 OnInit() 上的服务并获取模板如下...

template.component.ts 是:

 import  Component, OnInit, Input  from '@angular/core';
 import  template from '../core/model/template';
 import  templateService  from '../core/service/template.service';


 @Component(
    selector: 'app-template',
    templateUrl: './template.component.html',
    styleUrls: ['./template.component.css'],
    providers: [templateService ]

)
export class TemplateComponent implements OnInit 

    displayTemplate: template;

    private _isDraftEditing: boolean;
    get isDraftEditing(): boolean 
        return this._isDraftEditing;
    
    set isDraftEditing(draftediting: boolean) 
        this._isDraftEditing = draftediting;
    

    getErrorMessage: any;

    constructor(
        private templateService: templateService )  

    ngOnInit() 
        this.isDraftEditing = false;
        this.getTemplateByID('id inserted here from route');

    


    getTemplateByID(id: number): boolean 
        this.templateService.getTemplateById(id)
            .subscribe(
            getTemplate => 
                this.displayTemplate= getTemplate ;
                if (this.displayTemplate.status.code === 'draft') 
                    this.isDraftEditing = true;
                

            ,
            error => 
                this.getErrorMessage = <any>error;
                console.error(error);
                console.error('getErrorMessage=' + this.getErrorMessage);
            
            );
        if (this.getErrorMessage != null)  return false;  else  return true; 
    

我有一个进行单元测试的 template.component.spec 文件:

 describe('TemplateComponent...', () => 
        let component: TemplateComponent;
        let fixture: ComponentFixture<TemplateComponent>;
        let templateService: TemplateService,
            serverservice: ServerService,
            userService: UserService;
        let componentTemplateService: TemplateService;
        let testBedTemplateService: TemplateService;

        beforeEach(() => 
            serverservice = new MockServerService();
            userService = new MockUserService(serverservice);
           TemplateService = new MockTemplateService(serverservice);

        );


        beforeEach(() => 
            TestBed.configureTestingModule(
                declarations: [TemplateComponent],
                imports: [HttpModule, MdDialogModule, RouterTestingModule],
                schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA],
                providers: [ServerService, 
                     provide: TemplateService, useValue: templateService ,
                     provide: UserService, useValue: userService 
                ]
            )
               .overrideComponent(TemplateComponent, 
                    set: 
                        providers: [
                             provide: TemplateService, useValue: templateService ,
                             provide: UserService, useValue: userService 
                        ]
                    
                )
                .compileComponents();
        );

        beforeEach(() => 
            fixture = TestBed.createComponent(TemplateComponent);
            component = fixture.componentInstance;

            componentTemplateService = fixture.debugElement.injector.get(TemplateService);
            testBedTemplateService = TestBed.get(TemplateService);


        //mock objects
        it('...', () => 

            fixture.detectChanges();
            fixture.whenStable()
                .then(() => fixture.detectChanges());
            component.ngOnInit();
            expect(component.isDraftEditing).toBe(true);<--this line here: component is undefined!!!

        );
    );

基本上,我将带有模拟模板模型的模拟模板服务注入到组件中。就这么过来了。然而,尽管在组件上调用了 OnInit(),isDraftEditing 仍然是未定义的。我在这里错过了什么吗?根据我的阅读,我应该能够利用组件属性,不是吗?

【问题讨论】:

【参考方案1】:

好的,我自己解决了……

it('...', fakeAsync(() => 
        fixture.detectChanges();
        component.displayOutline = MockTemplateToCreate;
        component.isDraftEditing = true;
        component.ngOnInit();
        discardPeriodicTasks();
        tick(1000);
        fixture.detectChanges();
        const el = de.nativeElement;
        const content = el.textContent;
        expect(content).toContain('Save', '"Save"');

    ));

【讨论】:

以上是关于使用模拟服务时在业力测试中调用 OnInit() 后组件未定义的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Angular Oninit 仅在离开页面时才调用服务

如何使用不同的方法多次模拟调用 AWS 服务的 Golang 函数的单元测试?

如何提供模拟实体管理器来测试服务类?

对于 Java 测试,我应该模拟客户端还是模拟服务器

如何在服务层单元测试中模拟数据库结果?

使用proxyquire和mocha在单元测试中模拟方法调用时如何模拟时间延迟(超时)?