kojinkai
kojinkai

Reputation: 31

Mocking Angular 2 component dependencies in unit tests

I'm having some difficulty accessing the methods of a mocked service in Angular 2 when unit testing a component. I'm looking for a boilerplate for how to do this and my use case is fairly standard. Having read and tried to follow the Angular docs i'm still getting an issue accessing the methods of my mocked service.

At this stage I just want to give the component access to the mocked service's API and ultimately spy on the services login method to ensure it was called

login.page.ts

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { DBService } from '../../services/db/db.service';
import { TabsPage } from '../tabs/tabs.page';

@Component({
  templateUrl: 'login.page.html',
})
export class LoginPage {
  constructor(public navCtrl: NavController, public dbService: DBService) {}

  login() {
   this.dbService.login();
  }
}

db.service.mock.ts

export class MockDBService {

  public login(): string {
    return 'login service';
  }
}

login.page.spec.ts

import { LoginPage } from './login.page';
import { TestBed, inject, ComponentFixture } from '@angular/core/testing';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { NavController } from 'ionic-angular';
import { mockNavController } from 'ionic-angular/util/mock-providers';
import { DBService } from '../../services/db/db.service';
import { MockDBService } from '../../services/db/db.service.mock';

describe('Login Page:', () => {

  let fixture: ComponentFixture<LoginPage>;
  let component: LoginPage;
  let mockDBServiceInstance: MockDBService;

  beforeEach(() => {

    TestBed.configureTestingModule({
      schemas: [CUSTOM_ELEMENTS_SCHEMA],
      declarations: [
        LoginPage,
      ],
      providers: [
        {provide: NavController, useValue: mockNavController},
        {provide: DBService, useValue: MockDBService},
        LoginPage,
      ],
    });

    fixture = TestBed.createComponent(LoginPage);
    component = fixture.componentInstance;
    mockDBServiceInstance = TestBed.get(DBService);

  });

  describe('testing the login functionality', () => {
    it('should call the login method on the DBService', () => {
      spyOn(mockDBServiceInstance, 'login');
      component.login();
      expect(mockDBServiceInstance.login).toHaveBeenCalled();
    });
  });
});

This throws

Error: <spyOn> : login() method does not exist

to stdout

I've been at this for ages with no real joy so any tips on how to do this in an idiomatic way would be greatly appreciated.

Thanks

Upvotes: 1

Views: 1980

Answers (1)

Mezo Istvan
Mezo Istvan

Reputation: 2782

If you want to provide a mocked class, you have to do it with useClass:

{provide: DBService, useClass: MockDBService}

Upvotes: 3

Related Questions