发出值后 RxJS BehaviorSubject getValue 不一致(在 Jest 中测试时)
RxJS BehaviorSubject getValue inconsistency after value emitted (while testing in Jest)
我不明白为什么 .getValue()
returns Observable 的默认值而不是最后发出的值。在测试 Observable 时,它正确 returns 发出的值。
class TestA {
readonly aSource: BehaviorSubject<number> = new BehaviorSubject(null);
getA(): number {
return this.aSource.getValue();
}
promise(): void {
Promise.reject()
.catch(() => {
this.aSource.next(2);
console.log(this.getA()); // Outputs: 2
});
}
}
describe('TestA', () => {
it('promise', () => {
const a = new TestA();
a.promise();
// Test 1 OK
expect(a.aSource.asObservable()).toBeObservable(hot('a', {a: 2}));
// Test 2 FAIL (returns null)
expect(a.aSource.getValue()).toEqual(2);
// Test 3 FAIL (returns null)
expect(a.getA()).toEqual(2);
});
});
澄清一下,getValue()
方法在测试之外运行良好,它仅在使用 Jest 测试时失败。
谢谢!
原因是 catch
的回调函数的异步性质。所以我认为如果你将你的期望语句包装在 setTimeout
中,并且 运行 测试为异步它变成绿色。
第一个断言是异步的。在内部,它会解析 Observable
,所以你确实会得到 2
.
然而,当这待定时,其他两个断言被触发。而且它们是同步的。没有任何东西可以保证 .next
调用已经完成。所以你得到的还是初始值。
这就是为什么我建议不要使用 BehaviorSubject
的 .getValue
方法,而是正确地订阅它。这样,您就可以通过始终执行异步操作来避免此类混淆。
即使我这样做 Promise.reject()
代码也不是同步的,所以在这种情况下你需要刷新执行队列以测试该代码。
使用 Angular 辅助函数的解决方案是:
it('promise', fakeAsync(() => {
const a = new TestA();
a.promise();
flush();
expect(a.aSource.asObservable()).toBeObservable(hot('a', {a: 2}));
expect(a.aSource.getValue()).toEqual(2);
expect(a.getA()).toEqual(2);
}));
我不明白为什么 .getValue()
returns Observable 的默认值而不是最后发出的值。在测试 Observable 时,它正确 returns 发出的值。
class TestA {
readonly aSource: BehaviorSubject<number> = new BehaviorSubject(null);
getA(): number {
return this.aSource.getValue();
}
promise(): void {
Promise.reject()
.catch(() => {
this.aSource.next(2);
console.log(this.getA()); // Outputs: 2
});
}
}
describe('TestA', () => {
it('promise', () => {
const a = new TestA();
a.promise();
// Test 1 OK
expect(a.aSource.asObservable()).toBeObservable(hot('a', {a: 2}));
// Test 2 FAIL (returns null)
expect(a.aSource.getValue()).toEqual(2);
// Test 3 FAIL (returns null)
expect(a.getA()).toEqual(2);
});
});
澄清一下,getValue()
方法在测试之外运行良好,它仅在使用 Jest 测试时失败。
谢谢!
原因是 catch
的回调函数的异步性质。所以我认为如果你将你的期望语句包装在 setTimeout
中,并且 运行 测试为异步它变成绿色。
第一个断言是异步的。在内部,它会解析 Observable
,所以你确实会得到 2
.
然而,当这待定时,其他两个断言被触发。而且它们是同步的。没有任何东西可以保证 .next
调用已经完成。所以你得到的还是初始值。
这就是为什么我建议不要使用 BehaviorSubject
的 .getValue
方法,而是正确地订阅它。这样,您就可以通过始终执行异步操作来避免此类混淆。
即使我这样做 Promise.reject()
代码也不是同步的,所以在这种情况下你需要刷新执行队列以测试该代码。
使用 Angular 辅助函数的解决方案是:
it('promise', fakeAsync(() => {
const a = new TestA();
a.promise();
flush();
expect(a.aSource.asObservable()).toBeObservable(hot('a', {a: 2}));
expect(a.aSource.getValue()).toEqual(2);
expect(a.getA()).toEqual(2);
}));