等待观察者在Jest中完成

时间:2020-08-08 09:07:07

标签: javascript rxjs jestjs observable

我对Jest和RxJ相当陌生,并被要求测试Observable。

const testComponents = ['test-component-1', 'test-component-2', 'test-component-3']
const nrOfComponents = testComponents.length

test('Activities get added to the taskStack', (done) => {
    launcher.observable$.subscribe((state) => {
        expect(state.taskStack).toHaveLength(nrOfComponents)
        done()
        }
    )

    testComponents.forEach((name) => {
        addActivityToTaskStack(name, 'standard')
    })
})

显然,state.taskStack数组的预期行为是三个。但是,添加第一项后测试已经完成。我如何等待Observable完成,然后才运行断言?

2 个答案:

答案 0 :(得分:1)

第一个subscribe回调在每个值上运行。测试应在可观察到的完成时结束,并且还应处理可能很乏味的错误:

let subscription = launcher.observable$.subscribe(
 function onValue(state) {
   try {
     expect(state.taskStack).toHaveLength(nrOfComponents)
   } catch (err) {
     subscription.unsubscribe();
     done.fail(err);
   }
 },
 function onError(err) {
   subscription.unsubscribe();
   done.fail(err);
 },
 function onComplete() {
   done();
 }
)

如果一个可观察对象期望接收一个值然后完成,那么一种直接的方法是切换到promise,因为它们符合所描述的可观察对象的语义,并且由Jest固有地支持。

test('Activities get added to the taskStack', async () => {
    const state = await launcher.observable$.toPromise();
    expect(state.taskStack).toHaveLength(nrOfComponents)
})

如果有多个值,则可以在toPromise之前收集它们以进行断言,例如toArray运算符。

请注意,RxJS 7中不推荐使用toPromise,而推荐使用lastValueFrom

答案 1 :(得分:1)

您只能获取流的数量,并在完成可观察性时调用done()

launcher.observable$
  .pipe(
    take(3) // <- number of items to be added. It will be completed after 3 items
  )
  .subscribe(
    state => {
      expect(state.taskStack).toHaveLength(testComponents.length);
    },
    () => {},
    () => {
      done();
    }
  );

不确定如何触发observable,但是您可能需要更新expect表达式。

但是,以上代码将确保在添加3个项目之后完成测试。