最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Observable<void> doesn't invoke the subscriber - Stack Overflow

programmeradmin5浏览0评论

I'm struggling to get a unit test around an Observable to behave the way I expect. I'm using an Observable essentially just to notify that a process has pleted. There's no async code in the loggout function yet, but there will be when I implement all the logic. I don't need the observable to return any data, I just want it to invoke the subscriber as a signal that the logout is plete.

The problem is my Unit Tests revealed the subscriber is never actually invoked. I normally work with async/await, ironically because Observables tend to give me headaches by doing stuff like this, but I'm trying to get better at the front-end, which seems to prefer Observables.

This is a new Angular 9 application that I'm scaffolding up. Unit tests are running in Jest, and I'm running them through Wallaby.

Here's my troubleshooting:

I deliberately broke the function to verify my my unit test works.

The grey box on line 63 of my tests is Wallaby indicating that the test never executed that line. So naturally the test passed because the assertion was never checked.

If I change the observable to return a value I at least get the line to execute... sort of.

But I'm not getting getting the expected failure message from my mock. It should report "expected clearSession() to be called 1 times, was 0"

So I run Jest just to see what's going on and I get:

FAIL  src/app/auth/auth.service.spec.ts
● AuthService › logout › should destroy the session

1 timer(s) still in the queue.

  at node_modules/zone.js/dist/fake-async-test.js:621:31
  at ZoneDelegate.Object.<anonymous>.ZoneDelegate.invoke (node_modules/zone.js/dist/zone.js:386:30)
  at ProxyZoneSpec.Object.<anonymous>.ProxyZoneSpec.onInvoke (node_modules/zone.js/dist/proxy.js:117:43)
  at ZoneDelegate.Object.<anonymous>.ZoneDelegate.invoke (node_modules/zone.js/dist/zone.js:385:36)
  at Zone.Object.<anonymous>.Zone.run (node_modules/zone.js/dist/zone.js:143:47)

To make things really strange... if I fix the function everything is happy! But only so long as the Observable is returning a value, even though I'm only using the Observable to notify when the process is plete. But I haven't been able to get my actual assertion to fail, it failed because of something seemingly unrelated (The timer in queue? Whatever that means).

The verify function is from ts-mockito and works essentially like the expect(someSpy).toHaveBeenCalledTimes() function.

Is there some quirk about Observables that I'm missing?

I'm struggling to get a unit test around an Observable to behave the way I expect. I'm using an Observable essentially just to notify that a process has pleted. There's no async code in the loggout function yet, but there will be when I implement all the logic. I don't need the observable to return any data, I just want it to invoke the subscriber as a signal that the logout is plete.

The problem is my Unit Tests revealed the subscriber is never actually invoked. I normally work with async/await, ironically because Observables tend to give me headaches by doing stuff like this, but I'm trying to get better at the front-end, which seems to prefer Observables.

This is a new Angular 9 application that I'm scaffolding up. Unit tests are running in Jest, and I'm running them through Wallaby.

Here's my troubleshooting:

I deliberately broke the function to verify my my unit test works.

The grey box on line 63 of my tests is Wallaby indicating that the test never executed that line. So naturally the test passed because the assertion was never checked.

If I change the observable to return a value I at least get the line to execute... sort of.

But I'm not getting getting the expected failure message from my mock. It should report "expected clearSession() to be called 1 times, was 0"

So I run Jest just to see what's going on and I get:

FAIL  src/app/auth/auth.service.spec.ts
● AuthService › logout › should destroy the session

1 timer(s) still in the queue.

  at node_modules/zone.js/dist/fake-async-test.js:621:31
  at ZoneDelegate.Object.<anonymous>.ZoneDelegate.invoke (node_modules/zone.js/dist/zone.js:386:30)
  at ProxyZoneSpec.Object.<anonymous>.ProxyZoneSpec.onInvoke (node_modules/zone.js/dist/proxy.js:117:43)
  at ZoneDelegate.Object.<anonymous>.ZoneDelegate.invoke (node_modules/zone.js/dist/zone.js:385:36)
  at Zone.Object.<anonymous>.Zone.run (node_modules/zone.js/dist/zone.js:143:47)

To make things really strange... if I fix the function everything is happy! But only so long as the Observable is returning a value, even though I'm only using the Observable to notify when the process is plete. But I haven't been able to get my actual assertion to fail, it failed because of something seemingly unrelated (The timer in queue? Whatever that means).

The verify function is from ts-mockito and works essentially like the expect(someSpy).toHaveBeenCalledTimes() function.

Is there some quirk about Observables that I'm missing?

Share Improve this question asked Apr 26, 2020 at 18:32 GridDragonGridDragon 3,1453 gold badges35 silver badges44 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 17

I posted this question to Reddit last night. Just got an answer there that solved this, so posting here for anyone trying to solve the same.

Change of() to of(undefined)

Change of() to of(undefined) works for me

it('should call myCall', fakeAsync(() => {
    myService = TestBed.inject(MyService);
    const fakeRes: Observable<void> = of(undefined);
    spyOn(myService , 'myCall').and.callFake(() => fakeRes);
    tick();
    fixture.detectChanges();
    ponent.myMethod();
    expect(myService.myCall).toHaveBeenCalled();
}));
发布评论

评论列表(0)

  1. 暂无评论