简体   繁体   English

测试可观察到的RxJS是否跟踪最后发出的值(没有完整的信号)?

[英]Testing RxJS observable that tracks the last emitted value (no complete signal)?

I did some searching, but was unable to find a simple answer to my use-case. 我做了一些搜索,但是找不到我的用例的简单答案。 I apologize in advance if there already exists a sufficiently similar question on SO. 如果在SO上已经存在足够类似的问题,我预先表示歉意。

I have an observable, myObservable , that continuously streams a value from a store (ie it represents the state of the store). 我有一个可观察的myObservable ,它不断地从商店流式传输一个值(即,它代表商店的状态)。 I want to test, with Jest, that my observable is able to correctly update when changes happen to the store. 我想用Jest测试一下,当商店发生更改时,我的Observable是否能够正确更新。

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

So what I really want to do is something like the following: 因此,我真正想要做的是如下所示:

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

Basically I need a way to "tap" in to myObservable at any point in time to see what value was last emitted. 基本上,我需要一种在任何时间点“轻敲” myObservable ,以查看最后一次发出的值。 Sorry if this is a bit of a n00b question. 抱歉,这是一个n00b问题。

I am not pretty sure if it's an efficient way. 我不确定这是否有效。 But you can try this out. 但是您可以尝试一下。

This code is in Jasmine, I hope it would be somewhat similar in Jest. 这段代码在Jasmine中,我希望在Jest中会有些相似。

fit('Should test observable with store', fakeAsync(() => {
  const testData = [1, 2, 3, 4];
  let index = 0;

  myObservable.subscribe(t => {
    expect(t).toBe(testData[index]);
  });

  testData.forEach(td => {
    myStore.set(td)
    tick(100);
    index++;
  });
}));

This solution creates a subscription to receive expected values, perform assertion and end the test. 该解决方案创建一个订阅以接收期望值,执行断言并结束测试。

Though slightly long, it seems idiomatic to me and should be able to scale as your app's reactive needs grow. 尽管时间略长,但对我来说似乎很惯用,并且应该能够随着应用程序的响应需求增长而扩展。

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)
    )
  })
})

Good luck! 祝好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM