0

I am trying to pass a unit test for my function isAdmin(). The function should just return a role. It says 'user' cannot be read as I've taken a role from the information provided by the currentUser in .ts file. I'm not sure how to pass the user information in my test code(.spec.ts) file.

TypeError: Cannot read property 'user' of null

list-user.component.ts

constructor(public auth: AuthenticationService, public router: Router, public dialog: MatDialog) { }

ngOnInit() {
    const currentUser = JSON.parse(localStorage.getItem('currentUser')).user;
    this.role = currentUser.role;
}

isAdmin() {
    return this.role.toLowerCase() === 'admin';
  }

list-user.component.spec.ts

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ListUserComponent } from './list-user.component';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { CustomMaterialModule } from 'src/app/core/material.module';
import { HttpClientModule } from '@angular/common/http';
import { RouterTestingModule } from '@angular/router/testing';
import { from } from 'rxjs';

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

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ ListUserComponent ],
      imports: [
        FormsModule,
        ReactiveFormsModule,
        CustomMaterialModule,
        HttpClientModule,
        RouterTestingModule
    ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(ListUserComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });



it('should call isAdmin()', () => {

  let role = 'admin'
  spyOn(component, 'isAdmin').and.callFake(() => {
    return from([role]);
  });
  component.isAdmin();
  expect(component.role).toBe(role);
});

});
  • As written your function does not return a role. It returns a boolean if `this.role` is equal to the string `admin`. Also your test stubs the function and calls a fake in its place, so your function never actually gets called (and therefore is not tested) which is unlikely to be what you want. – dmcgrandle Feb 06 '19 at 07:01
  • 1
    You need to mock the localStorage for this test to pass. Here is an example: https://medium.com/@armno/til-mocking-localstorage-and-sessionstorage-in-angular-unit-tests-a765abdc9d87 – De Wet van As Feb 06 '19 at 07:04

1 Answers1

1

It may be null because localStorage may not have been initialized with currentUser key. Therefore you need to check if a value with currentUser key exists

ngOnInit() {
    const currentUser = JSON.parse(localStorage.getItem('currentUser'));
    this.role = currentUser ? currentUser.user.role : DEFAULT_ROLE; // You have to define a default role
}

Update

And also, as @DeWetvanAs stated in the comment,you need to mock localStorage while unit testing.

An example: How to mock localStorage in JavaScript unit tests?

Harun Yilmaz
  • 8,281
  • 3
  • 24
  • 35