Angular with Jasmine:beforeEach()中的异步和它()中的异步之间是否存在冲突?

时间:2018-03-02 13:00:36

标签: angular asynchronous jasmine

我的目标是测试API调用,并考虑延迟。我受到了this post的启发。

我设计了一个沙箱,其中模拟API需要1000毫秒才能响应并更改全局变量result的值。测试在500毫秒后和1500毫秒后检查值。

以下是最后一次测试失败的代码:

    let result: number;

    const mockAPICall = (delay: number): Observable<number> => {
        console.log('API called');
        return Observable.of(5).delay(delay);
    };

    beforeEach(() => {
        console.log('before each');
    });

    it('time test', async(() => {
        result = 0;
        const delay = 1000;
        console.log('start');

        mockAPICall(delay).subscribe((apiResult: number) => {
            console.log('obs done');
            result = apiResult;
        });

        console.log('first check');
        expect(result).toEqual(0);

        setTimeout(() => {
                console.log('second check');
                expect(result).toEqual(0);
            }, 500
        );

        setTimeout(() => {
                console.log('third check');
                expect(result).toEqual(0);
            }, 1500
        );
    }));

最后一次测试确实按预期失败了,我在日志中得到了这个:

before each
API called
first check
second check
obs done
third check

现在,如果我在async()中放置beforeEach()

    beforeEach(async(() => {
        console.log('async before each');
    }));

,测试通过,我只在日志中得到这个:

async before each
API called
first check

我没想到。为什么会这样?幕后发生了什么?

注意:我在将来的测试中需要async()中的这个beforeEach(),因为我会使用testBedcompileComponents

1 个答案:

答案 0 :(得分:2)

您的问题源于在测试期间使用区域的不幸边缘情况,并在Angular文档here中进行了概述。

  

使用done()编写测试函数比asyncfakeAsync更麻烦。但它偶尔也是必要的。例如,在测试涉及async或RxJS fakeAsync运算符的代码时,您无法调用intervalTimer()delay()

这与rxjs中的计时器的实现有关,并且有很多好的材料可以帮助您使用TestSchedulers来测试使用其中一些的rxjs代码运算符(如delay)。

对于您的情况,您可以选择重构您的测试以不使用delay运算符,或者您可以使用Jasmine提供的done()

let result: number;

const mockAPICall = (delay: number): Observable<number> => {
    console.log('API called');
    return Observable.of(0).delay(delay); // changed from 5 -> 0, to make tests pass
};

beforeEach(async(() => {
    console.log('async before each');
}));

it('time test', done => async(() => {
    result = 0;
    const delay = 1000;
    console.log('start');

    mockAPICall(delay).subscribe((apiResult: number) => {
        console.log('obs done');
        result = apiResult;
    });

    console.log('first check');
    expect(result).toEqual(0);

    setTimeout(() => {
            console.log('second check');
            expect(result).toEqual(0);
        }, 500
    );

    setTimeout(() => {
            console.log('third check');
            expect(result).toEqual(0);
            done(); // indicate that the test is complete
        }, 1500
    );
})());

因为delayasync一起使用时出现问题,所以Jasmine正在结束&#34;尽早测试 - 你不会看到失败,但你也不会看到一些日志记录。