首页 > 解决方案 > 测试跟踪最后发出的值的 RxJS observable(没有完整的信号)?

问题描述

我做了一些搜索,但无法找到我的用例的简单答案。如果已经存在关于 SO 的足够相似的问题,我提前道歉。

我有一个 observable ,myObservable它不断地从商店流式传输一个值(即它代表商店的状态)。我想用 Jest 测试我的 observable 是否能够在商店发生更改时正确更新。

// i.e. every time the value changes, an event is emitted by myObservable
myObservable.subscribe(x => console.log(x))

所以我真正想做的是以下内容:

await myStore.set(0)
// insert here: check that `myObservable` stream is a 0
await myStore.set(5)
// insert here: check that `myObservable` stream is a 5

基本上我需要一种myObservable在任何时间点“挖掘”的方法,以查看最后发出的值。对不起,如果这是一个有点 n00b 的问题。

标签: javascripttestingrxjsjestjsrxjs6

解决方案


此解决方案创建订阅以接收预期值、执行断言并结束测试。

虽然有点长,但对我来说似乎是惯用的,并且应该能够随着应用程序的响应式需求的增长而扩展。

import { from, Observable, of } from 'rxjs'
import { concatMap, finalize, take, tap, toArray } from 'rxjs/operators'

// sample "definitions" to make the example compile
// replace "myObservable", "myStore" with actual code for expected result
const myObservable: Observable<number> = of(123)
const myStore: {
  set: (number) => Promise
} = null as any

describe('my test', () => {
  it('is an example', done => {
    // configure observable to assert emitted values
    myObservable.pipe(
      // this subscription will complete after emitting 2 values
      take(2),
      // put all the values into a single array
      toArray(),
      // assert the values (that has been converted to array)
      tap(vals => expect(vals).toBe([0, 5]),
      // this will ensure the test does not 'hang' on observable error
      finalize(() => {
        // test will fail if assertion did not happen
        expect.assertions(1)
        done()
      })
    ).subscribe()

    // --- pick preferred way to execute - "set store value"
    // option 1: set 0 then set 5 (using observables)
    from(myStore.set(0)).pipe(
      concatMap(() => myStore.set(5))
    ).subscribe()

    // option 2: set 0 then set 5 (using promises)
    myStore.set(0).then(() =>
      myStore.set(5)
    )
  })
})

祝你好运!


推荐阅读