Angular: Unit Test Mock Service
Tags: angular, jasmine, unittest, patterns
Published: 2021-08-16 12:57:43

---
title: Angular: Unit Test Mock Service
published: true
description: When testing other code, I wanted to mock the calls and data responses to ensure stability.
tags: Angular, Jasmine, UnitTest, Patterns
series: Angular Unit Testing
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/305o78pjodykvjcdrcuv.png
---

So, I needed to mock a service.

In particular, I wanted to mock the API Handler Service. This service is the abstraction layer I use to interact with the back-end. There's often a lot going on here.

When testing other code, I wanted to mock the calls and data responses to ensure stability.

## Mocking Tools

While there are a lot of tools that can mock or replace an HTTP server, what I wanted to do was mock THIS service so that other code had consistent data coming back.

### Starting Code

I started with something like this ...

```typescript
// createSpyObj returns the attached OBJECT,
// if a function is attached, that is what is
// returned (not executed).
let MockApiHandlerService = jasmine.createSpyObj('ApiHandlerService', {
  ...
  getChartData: Promise.resolve(chartData),
  getEventDetail: Promise.resolve(eventDetail),
  getEventSummary: Promise.resolve(eventSummary),
  ...
});

export default MockApiHandlerService;
```

Yes, there are a lot of other functions I am not covering. These show the basics. The `chartData`, `eventDetail`, and `eventSummary` are data points listed higher in the file that I could use as mock data.

This code worked great.

And YES, I left the comment in ... after creating functions to execute. I have this on any `jasmine.createSpyObject` in my code to remind me.

These values are what are returned ... regardless of what is passed to the function.

## Tying this into Jasmine

First, the actual and mock service need imported ...

```typescript
import { ApiHandlerService } from '@core/services/api-handler.service';
import MockApiHandlerService from '@shared/_spec-tools/mock-api-handler.service';
```

Then, in the `beforeEach`, `providers` the services are used like this ...

```typescript
beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [ ... ],
      declarations: [ ... ],
      providers: [
        { provide: ApiHandlerService, useValue: MockApiHandlerService }
      ]
    })
    .compileComponents();
  });
```

## Issues

### Changing the Value

The first issue I has was that I wanted different data returned on one of the functions.

What I found was that I was changing the value returned for other tests doing something like this.

```typescript
MockApiHandlerService.getUsers.and.returnValue(Promise.resolve(null));
```

What I wound up having to do to correct this was to capture the "old" value and replace it after the test expects ...

```typescript
const oldValue = MockApiHandlerService.getUsers;
MockApiHandlerService.getUsers.and.returnValue(Promise.resolve(null));

...
MockApiHandlerService.getUsers = oldValue;
```

### Resetting the Calls

Additionally, I ran into issues resetting calls and checking to see the number of times a service function was called in a test.

Initially, I was clearing them per test, but after the first time I implemented something like this ...

```typescript
// createSpyObj returns the attached OBJECT,
// if a function is attached, that is what is
// returned (not executed).
let MockApiHandlerService = jasmine.createSpyObj('ApiHandlerService', {
  ...
  getChartData: Promise.resolve(chartData),
  getEventDetail: Promise.resolve(eventDetail),
  getEventSummary: Promise.resolve(eventSummary),
  ...
});

MockApiHandlerService._reset = () => {
  MockApiHandlerService.getChartData.calls.reset();
  MockApiHandlerService.getEventDetail.calls.reset();
  MockApiHandlerService.getEventSummary.calls.reset();
};

export default MockApiHandlerService;
```

This pattern then allowed me to clear the calls before each test run ...

```typescript
beforeEach(() => {
  MockApiHandlerService._reset();
});
```

## Summary

Throughout this process, I learned a lot of things about mocking a service. In particular, one that was used as frequently as this one throughout the application.

When testing other code, I wanted to mock the calls and data responses to ensure stability. With the mock service above, I was able to attain all the stated goals.