Angular Testing: Mock Private Functions

How to mock a private function in your automated Angular tests with Jasmine or Jest

Image for post
Image for post
Photo by Overture Creations on Unsplash

Credits

Test Setup

import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';

interface DogResponse {
message: string;
status: string;
}

@Injectable({
providedIn: 'root'
})
export class DoggosService {

constructor(private httpClient: HttpClient) {
}

async findDoggo(): Promise<string | null> {
const response: DogResponse = await this.searchDoggos();

if (!response) {
return null;
}

return response.message;
}

private searchDoggos(): Promise<DogResponse> {
const url = 'https://dog.ceo/api/breeds/image/random';
return this.httpClient.get<DogResponse>(url).toPromise();
}
}

Failing Unit Test

import {TestBed} from '@angular/core/testing';
import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';

import {DoggosService} from './doggos.service';

describe('DoggosService', () => {
let httpTestingController: HttpTestingController;
let service: DoggosService;

beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule]
});

httpTestingController = TestBed.get(HttpTestingController);
service = TestBed.get(DoggosService);
});

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

it('should fetch a doggo', async () => {
const mockUrl = 'https://images.dog.ceo/breeds/setter-irish/n02100877_1965.jpg';
const data: string | null = await service.findDoggo();

expect(data).not.toBe(null);
expect(data).toEqual(mockUrl);
});
});
Image for post
Image for post

Mock A Private Function With Jasmine

it('should fetch a doggo', async () => {
const mockUrl =
'https://images.dog.ceo/breeds/setter-irish/n02100877_1965.jpg';

const handleSpy = spyOn(DoggosService.prototype as any,
'searchDoggos');
handleSpy.and.callFake(() => {
return new Promise((resolve) => {
resolve({
message: mockUrl,
status: 'success'
});
});
});

const data: string | null = await service.findDoggo();

expect(data).not.toBe(null);
expect(data).toEqual(mockUrl);

expect(handleSpy).toHaveBeenCalled();
});
Image for post
Image for post

Mock A Private Function With Jest

it('should fetch a doggo', async () => {
const mockUrl =
'https://images.dog.ceo/breeds/setter-irish/n02100877_1965.jpg';

const handleSpy = jest.spyOn(DoggosService.prototype as any,
'searchDoggos');
handleSpy.mockImplementation(() => {
return new Promise(resolve =>
resolve({
message: mockUrl,
status: 'success'
})
);
});

const data: string | null = await service.findDoggo();

expect(data).not.toBe(null);
expect(data).toEqual(mockUrl);

expect(handleSpy).toHaveBeenCalled();
});

Summary

Freelancer by day | Creator of DeckDeckGo by night | Organizer of the Ionic and IndieHackers Zürich Meetup

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store