单元测试不适用于扩展基数 class 的 class

Unit test not behaving for a class that extends a base class

我正在努力测试一个组件 class,它扩展了另一个抽象 class。

两个class如下:

export abstract class BaseListComponent {
    constructor(
        protected someImportantService: SomeImportantService
    ){

    }

    handleListInitialization() {
        // Do lots of things
        this.doOtherStuff();
    }

    /**
     * @abstract doOtherStuff Function
     */
    protected abstract doOtherStuff( );
}


export class MyListComponent extends BaseListComponent {
    constructor(
        someImportantService: SomeImportantService,
        private listService: ListService
    ) {
        super( someImportantService );
    }

    doStuff = () => {
        this.handleListInitialization();
    }

    doOtherStuff(){
        this.listService.getThings().then(() => {
            // process response...
         })
    }
}

我正在尝试测试在 MyListComponent 中调用 doStuff 时会导致在 doOtherStuff 方法中调用 listService.getThings()

describe('When calling doStuff()', () => {
        it('should call getThings from the ListService instance', (  ) => {
            spyOn(component.listService, 'getThings').and.returnValue(Promise.then({foo: 'bar'}));
            component.doStuff();
            expect(component.listService.getThings).toHaveBeenCalled();
        });
    });

执行此测试时,我收到一条错误消息,指出从未调用过间谍程序,但奇怪的是,我的覆盖率报告显示我的 doOtherStuff() 实现的行已完全覆盖。

如果我在我的测试套件中改为调用 doOtherStuff(),那么测试就会顺利通过。

我不明白为什么会这样,我想知道我的抽象基础 class 是否以某种方式错误地实现了,尽管当 运行 应用程序正常工作时期待。

这可能是什么问题?

您需要 post 编写更多代码来创建 component,也许它被模拟了,在这种情况下,失败是意料之中的。 类 及其继承看起来不错,在描述的情况下应该可以通过测试。

问题是当 doOtherStuff 被调用时,就在那一刻你是 subscribing/attending 承诺。

如果你想接收this.listService.getThings()的值,你需要等到下一个时钟被执行。

要处理此问题,您可以使用 Angular 中的 fakeAysnc and tick

我认为我们可以像这样使用 fakeAsync 重写您的测试:

describe('When calling doStuff()',() => {
        it('should call getThings from the ListService instance',  fakeAsync(() => {
            component.doStuff();
            tick();
            fixture.detectChanges();
            spyOn(component.listService, 'getThings').and.returnValue(Promise.then({foo: 'bar'}));
            tick();
            fixture.detectChanges();
            expect(component.listService.getThings).toHaveBeenCalled();
        }));
});

它应该可以用。