Javascript 测试RxJS observable跟踪最后发出的值(无完整信号)?
我做了一些搜索,但找不到我的用例的简单答案。如果已经存在足够类似的问题,我提前道歉 我有一个可观察的,Javascript 测试RxJS observable跟踪最后发出的值(无完整信号)?,javascript,testing,rxjs,jestjs,rxjs6,Javascript,Testing,Rxjs,Jestjs,Rxjs6,我做了一些搜索,但找不到我的用例的简单答案。如果已经存在足够类似的问题,我提前道歉 我有一个可观察的,myObservable,它连续地从一个存储流式传输一个值(即,它表示存储的状态)。我想用Jest测试我的observable是否能够在存储发生更改时正确更新 //即每次值更改时,myObservable都会发出一个事件 myObservable.subscribe(x=>console.log(x)) 所以我真正想做的是如下所示: wait myStore.set(0) //在此处插入:检查
myObservable
,它连续地从一个存储流式传输一个值(即,它表示存储的状态)。我想用Jest测试我的observable是否能够在存储发生更改时正确更新
//即每次值更改时,myObservable都会发出一个事件
myObservable.subscribe(x=>console.log(x))
所以我真正想做的是如下所示:
wait myStore.set(0)
//在此处插入:检查“myObservable”流是否为0
等待myStore。设置(5)
//在此插入:检查“myObservable”流是否为5
基本上,我需要一种方法,在任何时间点“点击”到
myObservable
,以查看上次发出的值。如果这是一个n00b问题,很抱歉。我不确定这是否是一个有效的方法。但是你可以试试这个
这段代码是用Jasmine编写的,我希望它在开玩笑时有点类似
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++;
});
}));
我不太确定这是不是一种有效的方法。但是你可以试试这个 这段代码是用Jasmine编写的,我希望它在开玩笑时有点类似
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++;
});
}));
此解决方案创建订阅以接收预期值、执行断言和结束测试 虽然有点长,但在我看来,它似乎是惯用的,应该能够随着应用程序反应性需求的增长而扩展
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)
)
})
})
import{from,Observable,of}from'rxjs'
从“rxjs/operators”导入{concatMap,finalize,take,tap,toArray}
//示例“定义”使示例得以编译
//将“myObservable”、“myStore”替换为预期结果的实际代码
常数myObservable:Observable=of(123)
康斯特myStore:{
集合:(数字)=>承诺
}=与任何值一样为空
描述('我的测试',()=>{
它('是一个例子',完成=>{
//配置observable以断言发出的值
myObservable.pipe(
//此订阅将在发出2个值后完成
以(2)为例,
//将所有值放入一个数组中
toArray(),
//断言值(已转换为数组)
点击(VAL=>expect(VAL).toBe([0,5]),
//这将确保测试不会“挂起”可观察到的错误
完成(()=>{
//若断言未发生,测试将失败
expect.assertions(1)
完成()
})
).subscribe()
//---选择首选执行方式-“设置存储值”
//选项1:设置0,然后设置5(使用可观测值)
从(myStore.set(0))管道(
concatMap(()=>myStore.set(5))
).subscribe()
//选项2:设置0,然后设置5(使用承诺)
myStore.set(0)。然后(()=>
myStore.set(5)
)
})
})
祝您好运!此解决方案创建订阅以接收预期值、执行断言并结束测试 虽然有点长,但在我看来,它似乎是惯用的,应该能够随着应用程序反应性需求的增长而扩展
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)
)
})
})
import{from,Observable,of}from'rxjs'
从“rxjs/operators”导入{concatMap,finalize,take,tap,toArray}
//示例“定义”使示例得以编译
//将“myObservable”、“myStore”替换为预期结果的实际代码
常数myObservable:Observable=of(123)
康斯特myStore:{
集合:(数字)=>承诺
}=与任何值一样为空
描述('我的测试',()=>{
它('是一个例子',完成=>{
//配置observable以断言发出的值
myObservable.pipe(
//此订阅将在发出2个值后完成
以(2)为例,
//将所有值放入一个数组中
toArray(),
//断言值(已转换为数组)
点击(VAL=>expect(VAL).toBe([0,5]),
//这将确保测试不会“挂起”可观察到的错误
完成(()=>{
//若断言未发生,测试将失败
expect.assertions(1)
完成()
})
).subscribe()
//---选择首选执行方式-“设置存储值”
//选项1:设置0,然后设置5(使用可观测值)
从(myStore.set(0))管道(
concatMap(()=>myStore.set(5))
).subscribe()
//选项2:设置0,然后设置5(使用承诺)
myStore.set(0)。然后(()=>
myStore.set(5)
)
})
})
祝你好运!它感觉很笨重,但我想这可能行得通?我唯一的问题是测试如何知道一切都完成了?函数可能会在调用最后的
expect
语句之前完成(在最后的更改之后)。勾号(100)将确保所有其他回调都已执行,这是假设myStore.set()
永远不会超过100ms?感觉很笨拙,但我想这可能行得通?我唯一的问题是测试如何知道所有事情都完成了?函数可能会在调用最终的expect
语句之前完成(在最终更改之后)。勾号(100)将确保执行所有其他回调是否假设myStore.set()
的时间从不超过100ms?是否可以将myObservable
当前实现为主题?另一个问题-是否从myStore.set()返回
一个承诺,正如您的问题所显示的那样?如果是,它是否会转化为一个有意义的值?@dmcgrandle是的,它是一个主题
。是的,myStore.set()
是一个承诺,但它没有解决任何问题。只是我们知道,一旦承诺得到解决,交易就完成了。myObservable
当前是否作为主题实现?另一个问题-是否从myStore.set()返回
一个承诺,正如您的问题所显示的那样?如果是,它是否会解析为一个有意义的值?@dmcgrandle是的,它是一个主题
。是的,myStore.set()
是一个承诺,但它不会解析任何内容。只是我们知道,一旦