我的目标是测试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()
,因为我会使用testBed
和compileComponents
。
答案 0 :(得分:2)
您的问题源于在测试期间使用区域的不幸边缘情况,并在Angular文档here中进行了概述。
使用
done()
编写测试函数比async
和fakeAsync
更麻烦。但它偶尔也是必要的。例如,在测试涉及async
或RxJSfakeAsync
运算符的代码时,您无法调用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
);
})());
因为delay
与async
一起使用时出现问题,所以Jasmine正在结束&#34;尽早测试 - 你不会看到失败,但你也不会看到一些日志记录。