How to Run Unit Test Case for Toast Message in Angular Service?

I am working with an app based on Angular 12. I have service called notification service which handles toast messages from ngx-toastr library.

This is how that service looks like:

export class NotificationService {
  constructor(private toastr: ToastrService) {}

  showSuccess(message: string = 'Success ', note: string = ''): void {
    this.toastr.success(message, note);
  }

  showError(message: string = 'Error ', note: string = 'Try again'): void {
    this.toastr.error(message, note, {
      timeOut: 3000,
    });
  }
}

Service methods are working well, but when I am trying to implement tests for them then I get the following error:

NotificationService should test "showSuccess" method FAILED

Error: <spyOn> : could not find an object to spy upon for success()

These are the tests:

describe('NotificationService', () => {
  let notificationService: NotificationService,
    httpTestingController: HttpTestingController,
    toastrService: ToastrService,
    notificationServiceSpy: any;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [CommonModule, HttpClientTestingModule, ToastrModule.forRoot()],
      declarations: [],
      providers: [{ provide: ToastrService, useValue: toastrService }],
    }).compileComponents();
    notificationService = TestBed.inject(NotificationService);
    httpTestingController = TestBed.inject(HttpTestingController);
    toastrService = TestBed.inject(ToastrService);
  });

  it('should be created', () => {
    expect(notificationService).toBeTruthy();
  });

  it('should test "showSuccess" method', () => {
    spyOn(toastrService, 'success').and.callThrough();
  });

  afterEach(() => {
    httpTestingController.verify();
  });
});

Any help is appreciated. Thanks!

1 Answer

You are getting that message because when you do:

providers: [{ provide: ToastrService, useValue: toastrService }],

At that point in time, toastrService is undefined and then when you do spyOn(toastrService, 'success'); there is no success method to be spied on because toastrService is undefined.

I would mock toastrService.

Make the following changes, pay attention to lines that start with !!.

describe('NotificationService', () => {
  let notificationService: NotificationService,
    httpTestingController: HttpTestingController,
    // !! change this line to this
    toastrService: jasmine.SpyObj<ToastrService>,
    notificationServiceSpy: any;

  beforeEach(async () => {
    // !! add a new spy object before each test, now toastrService is not undefined
    toastrService = jasmine.createSpyObj<ToastrService>('ToasterService', ['error', 'success']);
    await TestBed.configureTestingModule({
      imports: [CommonModule, HttpClientTestingModule, ToastrModule.forRoot()],
      declarations: [],
      providers: [
       // !! provide NotificationService to the TestBed module because it is under test
       NotificationService,
       { provide: ToastrService, useValue: toastrService }],
    }).compileComponents();
    notificationService = TestBed.inject(NotificationService);
    httpTestingController = TestBed.inject(HttpTestingController);
    // !! don't need the below line, we already have access to the spy object
    // toastrService = TestBed.inject(ToastrService);
  });

  it('should be created', () => {
    expect(notificationService).toBeTruthy();
  });

  it('should test "showSuccess" method', () => {
    // !! you should not spyOn this anymore, toastrService has methods error
    // and success now which are both spies.
    // spyOn(toastrService, 'success').and.callThrough();
    // !! call the method
    service.showSuccess('hello world', 'hello');
    expect(toastrService.success).toHaveBeenCalledWith('hello world', 'hello');
  });

  afterEach(() => {
    httpTestingController.verify();
  });
});
4

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

David Miller

David Miller

Executive Financial & Market Analyst

David Miller brings 15 years of experience in global economics, personal finance strategy, and market dynamics. He specializes in turning complex economic trends into actionable insights for everyday readers.

Share this article
Twitter Facebook Pinterest