Несоответствие RxJS BehaviorSubject getValue после передачи значения (во время тестирования в Jest)
Я не понимаю почему .getValue()
возвращает значение по умолчанию для Observable, а не последнее выданное значение. При тестировании Observable он правильно возвращает выданное значение.
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.
Благодарность!
3 ответа
Даже если я сделаю 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);
}));
Причина в асинхронности функции обратного вызова catch
. Итак, я думаю, что если вы обернете свое выражение ожидания в setTimeout
, и запустите тест async, он стал зеленым.
Первое утверждение асинхронное. Внутренне он разрешитObservable
, так что вы действительно получите 2
.
Однако пока это ожидается, срабатывают два других утверждения. И они синхронны. Ничто не гарантирует вам, что в то время.next
звонок был сделан. Так вы все равно получите исходное значение.
Вот почему я бы рекомендовал не использовать .getValue
метод BehaviorSubject
а лучше подпишитесь на него как следует. Таким образом, вы избежите такой путаницы, всегда выполняя асинхронные операции.