6

I'm trying to write unit test for function in Angular app with debounceTime (rxjs). And use fakeAsync for asynchronous testing. And it looks that in test debounceTime gets resolved immediately even if I don't set tick() or set it with small interval like tick(500).

For example with delay(1000) instead of debounceTime(1000) fakeAsync works fine.

test:

describe('rr', () => {
    it('should get Date diff correctly in fakeAsync with rxjs scheduler', fakeAsync(() => {
        let result = null;
        of ('hello').pipe(debounceTime(1000)).subscribe(v => { result = v; });
        expect(result).toBeNull(); // But it is 'Hello' - debounceTime resolves immediately
        tick(1000);
        expect(result).toBe('hello');
...
  }));
})

stackblitz: https://stackblitz.com/edit/angular-ohhi9e?file=src%2Fapp%2Fapp.component.spec.ts

Alex Vovchuk
  • 2,828
  • 4
  • 19
  • 40

1 Answers1

5

The of operator completes immediately after its notification. If no additional notification is expected, debounceTime does not need to wait and thus notifies the moment the complete notification was emitted.

To achieve your result, try using a long-living observable like a Subject.

describe('rr', () => {
    it('should get Date diff correctly in fakeAsync with rxjs scheduler', fakeAsync(() => {
        let result = null;
        new BehaviourSubject ('hello').pipe(debounceTime(1000)).subscribe(v => { result = v; });
        expect(result).toBeNull();
        tick(1000);
        expect(result).toBe('hello');
...
  }));
})

Source: debounceTime on GitHub

_complete() { this.debouncedNext(); ... }

ggradnig
  • 13,119
  • 2
  • 37
  • 61