Search code examples
typescriptrxjs5ngrx-effects

Testing and mocking lettable operators in RxJS 5.5


Before lettable operator, I did a helper to modify debounceTime method, so it uses a TestScheduler:

export function mockDebounceTime(
    scheduler: TestScheduler,
    overrideTime: number,
): void {
    const originalDebounce = Observable.prototype.debounceTime;

    spyOn(Observable.prototype, 'debounceTime').and.callFake(function(
        time: number,
    ): void {
        return originalDebounce.call(
            this,
            overrideTime,
            scheduler,
        );
    });
}

So the test of the following Observable was easy:

@Effect()
public filterUpdated$ = this.actions$
    .ofType(UPDATE_FILTERS)
    .debounceTime(DEFAULT_DEBOUNCE_TIME)
    .mergeMap(action => [...])

With lettable operators, the filterUpdated$ Observable is written like that:

@Effect()
public filterUpdated$ = this.actions$
    .ofType(UPDATE_FILTERS)
    .pipe(
        debounceTime(DEFAULT_DEBOUNCE_TIME),
        mergeMap(action => [...])
    );

I cannot patch the debounceTime operator anymore ! How can I pass the testScheduler to the debounceTime operator ?


Solution

  • You can use the second argument that accepts a custom Scheduler.

      debounceTime(DEFAULT_DEBOUNCE_TIME, rxTestScheduler),
    

    All code

    import { Scheduler } from 'rxjs/scheduler/Scheduler';
    import { asap } from 'rxjs/scheduler/asap';
    
    @Injectable()
    export class EffectsService {
      constructor(private scheduler: Scheduler = asap) { }
    
      @Effect()
      public filterUpdated$ = this.actions$
        .ofType(UPDATE_FILTERS)
        .pipe(
            debounceTime(DEFAULT_DEBOUNCE_TIME, this.scheduler),
            mergeMap(action => [...])
        );
    }
    

    Then on test

    describe('Service: EffectsService', () => {
      //setup
      beforeEach(() => TestBed.configureTestingModule({
        EffectsService, 
        { provide: Scheduler, useValue: rxTestScheduler} ]
      }));
    
      //specs
      it('should update filters using debounce', inject([EffectsService], service => {
        // your test
      });
    });