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

Col*_*oli 5 asynchronous jasmine angular

我的目标是测试API调用,考虑延迟.我受到这篇文章的启发.

我设计了一个沙箱,其中模拟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
        );
    }));
Run Code Online (Sandbox Code Playgroud)

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

before each
API called
first check
second check
obs done
third check
Run Code Online (Sandbox Code Playgroud)

现在,如果我把一个async()beforeEach():

    beforeEach(async(() => {
        console.log('async before each');
    }));
Run Code Online (Sandbox Code Playgroud)

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

async before each
API called
first check
Run Code Online (Sandbox Code Playgroud)

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

注意:我将来需要这个async(),beforeEach()因为我会使用testBedcompileComponents.

小智 3

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

用 , 编写测试函数比和done()更麻烦。但偶尔还是有必要的。例如,在测试涉及或 RxJS运算符的代码时,您不能调用或。asyncfakeAsyncasyncfakeAsyncintervalTimer()delay()

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

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

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
    );
})());
Run Code Online (Sandbox Code Playgroud)

delay因为使用with时出现问题async,Jasmine 提前“结束”测试 - 您不会看到失败,但也不会看到一些日志记录语句。