javascript - Angular 6 - 单元测试构造函数中的订阅函数

标签 javascript angular unit-testing karma-jasmine

我一直在尝试对该服务的订阅功能进行单元测试。查看 istanbul 生成的代码覆盖率报告,我可以看到这段代码没有被覆盖。

代码

layout.component.ts

import {Component, HostListener, Input} from '@angular/core';

import { LayoutService } from './layout.service';

import { some } from 'lodash';

@Component({
    selector: 'cgm-layout',
    templateUrl: './layout.component.html',
    styleUrls: ['./layout.component.scss'],
    providers: [LayoutService]
})
class LayoutComponent {

    message: any;

    constructor(
        private service: LayoutService
    ) {
        service.messagePublished$.subscribe(
            message => {
                this.setMessage(message);
            }
        );
    }

    setMessage(message): void {
        this.message = message;
        setTimeout(() => {
            this.message = null;
        }, 7000);
    }

}

export {
    LayoutComponent
};

这是我的单元测试

layout.component.spec.ts

import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { of } from 'rxjs';
import { LayoutComponent } from './layout.component';
import { LayoutService } from './layout.service';

describe('LayoutComponent', () => {
    let component: LayoutComponent;
    let fixture: ComponentFixture<LayoutComponent>;
    let service;

    beforeEach(async(() => {
        service = new LayoutService();
        mockLayoutService = jasmine.createSpyObj('LayoutService', ['messagePublished$']);
        TestBed.configureTestingModule({
            declarations: [
                LayoutComponent,

            ],
            providers: [
                LayoutService
            ],
            schemas: [
                NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA
            ]
        })
            .compileComponents();
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(LayoutComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();

        component.message = 'Garbage';
    });

    it('should call messagePublished', () => {
        spyOn(service.messagePublished$, 'subscribe');
        TestBed.createComponent(LayoutComponent);

        expect(service.messagePublished$.subscribe).toHaveBeenCalled();
    });

    describe('setMessage', () => {

        it('should set the Message', fakeAsync(() => {
            component.setMessage('Message');

            expect(component.message).toBe('Message');
            tick(7000);
            expect(component.message).toBeNull();
        }));

    });
});

所以代码似乎永远不会越过“service.messagePublished$.subscribe”部分。这是 code coverage report .

我得到的错误是“Expected spy subscribe to have been called”,我猜这是你在没有覆盖该代码块时得到的错误。

最佳答案

我建议您将订阅从构造函数移至 ngOnInit。 Angular 创建了几个生命周期 Hook ,它们在创建组件 (ngOnInit) 时调用,在数据更改或销毁时调用 - 参见 Angular lifecycle hooks .

这样您就可以通过调用 ngOnInit() 方法来测试您的代码。

如果您无法更改代码,您可以尝试创建一个组件实例并检查是否像下面的伪代码那样调用了您的方法:

import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { of } from 'rxjs';
import { LayoutComponent } from './layout.component';
import { LayoutService } from './layout.service';

describe('LayoutComponent', () => {
    let component: LayoutComponent;
    let fixture: ComponentFixture<LayoutComponent>;
    let serviceSpy: jasmine.SpyObj<LayoutService>;;

    beforeEach(async(() => {
        const spy = spyOn(service.messagePublished$, 'subscribe')
        TestBed.configureTestingModule({
            declarations: [
                LayoutComponent,

            ],
            providers: [
                { provide: LayoutService, useValue: spy }
            ],
            schemas: [
                NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA
            ]
        })
            .compileComponents();
            serviceSpy = TestBed.get(ValueService);
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(LayoutComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();

        component.message = 'Garbage';
    });

    it('should call messagePublished', () => {
        TestBed.createComponent(LayoutComponent);

        expect(service.messagePublished$.subscribe).toHaveBeenCalled();
    });

});

关于javascript - Angular 6 - 单元测试构造函数中的订阅函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53260326/

相关文章:

javascript - babel.transform() 函数不使用 .babelrc 或 package.json 配置

php - 如何在 iframe Facebook 应用程序中创建 "share"弹出窗口

javascript - 动态更改 javascript 过滤器函数内部的属性

python - 使用 Jenkins 运行站点正常运行时间和验证测试

android - apkbuilder 在将 powermock 添加到 android 测试项目时发现重复文件

javascript - 如何组合两个可观察量来创建新的可观察量?

javascript - Jquery 选择器 : whenever a user clicks on the Category 1/2/3, 其 `<ul>` 将可见

angular - 错误 : Can't resolve all parameters for Location: (? ) 在 angular7 webpack 应用程序中

javascript - 如何验证 contenteditable=true 的 html 标签?

c# - 滥用最小起订量来测试 if 条件