Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit test queryParams subscription (Angular5)

i'm having problems testing the logic inside ActivatedRoute queryParams subscription.

constructor(private router: Router, private route: ActivatedRoute, private auth: AuthService) {}

ngOnInit(): void {
  this.route.queryParams.subscribe((params:any) => {
    if(params['data']) {
      this.handle(params['data']);
    } else {
      if (this.auth.isAuthenticated()) {
        this.router.navigate(['/home']);
      }
    }
  });
}

I would like to test:

  • If this.handle() is triggered when mocked params['data'] is supplied
  • If there is no params and this.auth.isAuthenticated() returns true that this.router.navigate is called

I have tried multiple things and i'm running out of ideas.

My test file:

describe('TestComponent', () => {
  let component: TestComponent;
  let fixture: ComponentFixture<TestComponent>;

  const mockService = {
    navigate: jasmine.createSpy('navigate'),
    isAuthenticated: jasmine.createSpy('isAuthenticated'),
    queryParams: jasmine.createSpy('queryParams')
  };

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [TestComponent],
      providers: [
        { provide: Router, useValue: mockService },
        { provide: ActivatedRoute, useValue: mockService },
        { provide: AuthService, useValue: mockService }
      ]
    }).compileComponents();

    fixture = TestBed.createComponent(TestComponent);
    component = fixture.componentInstance;

    mockService.navigate.calls.reset();
  }));

  it('should create the test component', () => {
    expect(component).toBeTruthy();
  });

  it('should navigate away when authenticated', () => {
    mockService.isAuthenticated.and.returnValue(true);
    mockService.queryParams.and.callFake((data, params) => new Observable(o => o.next({ params: {} })));
    component.ngOnInit();
    expect(mockService.navigate).toHaveBeenCalledWith(['/home']);
  });
});

But with that i get TypeError: this.route.queryParams.subscribe is not a function. I know that mockService.isAuthenticated.and.returnValue(true); is working correctly because before using subscription to params i had only this if statement inside ngOnInit().

I have tried to change the mockService to:

const mockService = {
  navigate: jasmine.createSpy('navigate'),
  isAuthenticated: jasmine.createSpy('isAuthenticated'),
  queryParams: {
    subscribe: jasmine.create('subscribe')
  }
};

I also tried with:

const mockService = {
  navigate: jasmine.createSpy('navigate'),
  isAuthenticated: jasmine.createSpy('isAuthenticated'),
  queryParams: {
    subscribe: Observable.of({ params: {} })
  }
};

But no success, for those last two i get Expected spy navigate to have been called with [ [ '/home' ] ] but it was never called.

So does someone know how to correctly test logic inside querParams subscription?

like image 934
BoonZ Avatar asked May 24 '18 12:05

BoonZ


2 Answers

I can't say if it is too late to answer this or not, but maybe it will help new googlers...

I manage to solve that this way:

class ActivatedRouteMock {
  queryParams = new Observable(observer => {
    const urlParams = {
      param1: 'some',
      param2: 'params'
    }
    observer.next(urlParams);
    observer.complete();
  });
}

beforeEach(async(() => {
  TestBed.configureTestingModule({
    imports: [
      HttpClientTestingModule
    ],
    providers: [
      HttpClient,
      HttpHandler,
      ControlContainer,
      {
        provide: ActivatedRoute,
        useClass: ActivatedRouteMock
      }
    ]
  }).compileComponents();

  injector = getTestBed();
  httpMock = injector.get(HttpTestingController);
}));

That allows you to assert the logic inside your .subscribe(() => {}) method..

Hope it hepls

like image 118
Rafael Eduardo Paulin Avatar answered Nov 15 '22 21:11

Rafael Eduardo Paulin


You can use rxjs observable in useValue to mock it.

const router = {
  navigate: jasmine.createSpy('navigate')
};
beforeEach(async(() => {    
TestBed.configureTestingModule({
  imports: [
    RouterTestingModule.withRoutes([]),
    RouterTestingModule,
    PlanPrimengModule
  ],
  declarations: [YourComponent],
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  providers: [
    provideMockStore(),
    {
      provide: ActivatedRoute,
      useValue: {
        queryParams: of({
          param1: "value1",
          param1: "value2"
        })
      }
    },
    { provide: Router, useValue: router }
  ]
}).compileComponents();   }));
like image 39
Punit Sachan Avatar answered Nov 15 '22 21:11

Punit Sachan