Sangy_36
Sangy_36

Reputation: 73

How to unit test Rxjs combineLatest?

My component's ngOnInit does this

public ngOnInit() {
    this.ctrSubscription = combineLatest(this.route.queryParams, this.tags$).subscribe(async params => {
      if (Object.keys(params[0]).length > 0) {
        this.initView({ ...params[0] });
      }
      if (Object.keys(params[1]).length > 0) {
        this.wsTags = Object.values(params[1]);
      }
      if (params[0] && this.wsTags.length > 0) {
        this.searchWs({ ...params[0] }.q);
        this.pruneData();
      }
    });
  }

And this is how i am testing it

  it('should perform search and load the results', fakeAsync(() => {
    TestBed.get(ActivatedRoute).queryParams = of({ q: 'test' });
    const initSpy = spyOn<any>(component, 'initView').and.callThrough();
    const subSpy = spyOn<any>(component.tags$, 'subscribe');
    component.wsTags = ensureState(mockTags as any);
    flushMicroTasks();
    fixture.detectChanges();
    flushMicroTasks();
    expect(initSpy).toHaveBeenCalledWith({ q: 'test' });
    expect(subSpy).toHaveBeenCalled();
    expect(component.wsTags).toBe(Object.values(mockTags));
  }));

the spys are not getting called at all.I put a breakpoint when running tests to know if the value is passing or not , and i was able to catch the query params being passed correctly but still the if fails.

I tried going through the docs to understand better and also various similar questions here on stack overflow, i couldn't able to solve it. I am fairly new to writing unit tests, so any help will be appreciated. Thanks.

Upvotes: 0

Views: 1008

Answers (1)

AliF50
AliF50

Reputation: 18899

One potential issue is that you're mocking ActivatedRoute within the it block. This is too late, your ngOnInit runs after the first detectChanges after compileComponents.

When configuring your testing module, try:

describe('Put description of the test', () => {
  let component: YourComponent;
  let activatedRoute: ActivatedRoute;
  let fixture: ComponentFixture<YourComponent>;

  beforeEach(() => {
    TestBed.configureTestingModule({
     declarations: [ YourComponentToTest, 
      // other declarations if need be.
     ],
     providers: [
      provide: ActivatedRoute,
      useValue: {
       queryParams: of({ q: 'test" }),
      }
     ]
   }).compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(YourComponentToTest);
    component = fixture.componentInstance;
    activatedRoute = TestBed.get(ActivatedRoute);
    // ngOnInit is ran now -- after the first detectChanges
    fixture.detectChanges();
  });

  it('should do what you want', () => {
   // your arrange, act, and assertions.
  });
})

Make sure this.tags$ is initialized as well.

I did all of this freehand so there may be typo(s).

Upvotes: 1

Related Questions