我想在我的测试中模拟来自observable的值是按顺序进入的,一次一个(所以有时我想使用setTimeout(,0)来实现这个)我可以测试这个并且最后我想测试我的测试中的可观察订阅是否已输入(因为有时测试是成功的,因为它没有进入订阅的处理程序并且没有执行任何期望)。
为了理解在单元测试中如何处理observable,我尝试以下方法。
我有一个返回observable的函数。这只是一个模拟功能。 (通常,值来自另一个可从http获取值的observable。)
export function getObs(): Observable<string[]> {
let obs = Observable.create( (observer: Observer<string[]>) => {
observer.next([]);
observer.next(["x1", "x2"]);
observer.complete();
});
return obs;
}
describe( "aa ", () => {
fit("aa", async(() => {
let counter = 0;
getObs().subscribe(
(res:string[])=> {
counter++;
console.debug("---- iter " + counter + " res:" +res);
if( counter === 1)
expect(res.length).toBe(0);
if( counter === 2)
expect(res.length).toBe(2);
},
() => { console.debug("--- completed " + counter); }
);
console.debug("counter:"+counter);
expect(counter).toBe(2);
setTimeout(()=> expect(counter).toBe(2),0 );
}))
});
我希望observable发出两个值,然后完成。
输出如下:
DEBUG: '---- iter: 1 res:'
DEBUG: '---- iter: 2 res:x1,x2'
DEBUG: 'counter:2'
这里有几个问题,甚至更多我不理解的事情。
永远不会调用完成的回调。
订阅块后,计数器立即为2。我期待只有在setTimeout()里面才能看到计数器2.所以这引出了一个问题:这个代码是如何执行的?在哪个序列?
有或没有async
- 行为是一样的。 (再次,前一个问题获得重要性)。为什么?
我想在单元测试中掌握来自可观察的AND的值序列,以便在调用订阅处理程序的最后测试。 理想情况下,值序列应该在不同的刻度中,以模拟http响应,因此是异步的。
在第一个测试变体中,我complete
- 测试中的observable(但是我的测试中的完整处理程序仍未被调用),并且可观察值出现在相同的时间内。
现在这里是另一个变种:使用主题 - 但在这里我不知道complete
序列,我发送不同刻度的值。
export function getObs2(): Observable<string[]> {
const subject = new ReplaySubject<string[]>(1);
subject.next([]);
// subject.next(["x1", "x2"]);
setTimeout( () => subject.next(["x1", "x2"]), 0 );
return subject.asObservable();
}
fit("b", async(() => {
let counter = 0;
getObs2().subscribe(
(res:string[])=> {
counter++;
console.debug("---- iter: " + counter + " res:" +res);
if( counter === 1)
expect(res.length).toBe(0);
if( counter === 2)
expect(res.length).toBe(2);
},
() => { console.debug("--- completed " + counter); }
);
console.debug("counter:"+counter);
// expect(counter).toBe(2); <---- this fails as counter is 1 here
setTimeout(()=> expect(counter).toBe(20),0 ); // just to be print an error with the value of counter, to be sure that it reach here.
}))
结果是:
DEBUG: '---- iter: 1 res:'
DEBUG: 'counter:1'
DEBUG: '---- iter: 2 res:x1,x2'
[1] Expected 2 to be 20.
现在在getObs2()
我发出两个值 - 但是我在下一个tick中发出第二个值(我使用setTimeout),否则getObs2().subscribe
只输入一次而不是两次(为什么?)。所以我在单独的tick中发出值,这样订阅处理程序被调用两次。
现在计数器是1 - 在第一个刻度中执行我猜 - 我需要期望计数器在下一个刻度中为2。
不调用完整的处理程序。
如果此测试不是async
,会发生什么?我删除了async
和...
DEBUG: '---- iter: 1 res:'
DEBUG: 'counter:1'
DEBUG: '---- iter: 2 res:x1,x2'
这意味着最后一行没有被执行? (应该看错误)
setTimeout(()=> expect(counter).toBe(20),0 );
但setTimeout()
内的getObs2()
已执行....
有人可以解释一下发生了什么吗? 我显然没有使用单元测试sync / async&amp;可观察的&amp; setTimeout ....这种组合很难......
理想情况下我想:
在不同刻度中提供的可观察值(从使用setTimeout(,0)发送响应的MockBackend模拟)
每次打勾期间的具体测试
最后的特定测试(可能在观察完成后? - 但它在单元测试中永远不会完成 - 为什么?)
了解我可以从上面进行同步测试以及异步测试中的内容。 在第一个测试变体中,同步/异步策略中的行为是相同的。第二个测试:在同步的情况下 - 它不能在下一个刻度中检查计数器,但它可以在下一个刻度中发出一个可观察的值 - 这很奇怪。