Mocking dependencies in Angular
Don't create your own object to mock the dependency, use jasmine

I am a developer from Toronto, Canada and I enjoy writing about JavaScript, Angular and the .NET framework.
Search for a command to run...
Don't create your own object to mock the dependency, use jasmine

I am a developer from Toronto, Canada and I enjoy writing about JavaScript, Angular and the .NET framework.
No comments yet. Be the first to comment.
In this series, I will go over basics of writing tests for Angular based application artifacts
How to test Angular services that make Http calls
What does 99.99% mean?

Using Projections - getting related data

Expose an entity using HotChocolate

Reactive programming is somewhat of a shift in thinking on how you get values from a source of data. Instead of you asking the source every few seconds for an update, the source sends you data you are interested in over time. In other words, we are t...

Learn to create your own tags like control

It is quite common to have a component or a service that depends on another service. For example, a Directory service may need to get data from a Database service.
Here is an example of such a Directory service:
import {Injectable} from '@angular/core';
import {DatabaseService} from './database.service';
@Injectable()
export class DirectoryService {
constructor(private dbService: DatabaseService) {}
contacts(): string[] {
return this.dbService.getContacts();
}
}
In the code above, we see that the Directory service has a constructor with the DatabaseService injected to it by Angular. As such, whenever the Directory service is instantiated (i.e, Angular DI provides us an instance of the Directory service), it will also have an instance of the Database service provided into the constructor. Since we use the private keyword in the constructor, a local variable named dbService will be created and assigned to the value of the DatabaseService.
We know that Unit Tests should run in isolation. By that, I mean that when we test the Directory service, we should not be injecting the actual Database service into it. Instead, we should be creating a fake Database service that we have control over.
There are several reasons why we should not inject the actual dependency. Let us consider several (from many) scenarios of what could happen if we instantiated an actual instance of the Database service:
I have come across many different ways developers have mocked dependencies in Angular. For example, I have seen the following working code:
// Example 1 - verbose method of mocking
const mockDb = {
getContacts: () => ['A', 'B']
};
This works, but there is a better approach using the jasmine framework.
const mockDb = jasmine.createSpyObj('DatabaseService',['getContacts']);
The statement above gives us a mock of our service with a getContacts method inside it.
You may be asking yourself a question now. What does getContacts return? We will answer this question shortly.
Now that we have the mock database created, we can provide it to the TestBed, and the way to do it is with the configureTestingModule method.
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
DirectoryService,
{
provide: DatabaseService,
useValue: mockDb
}]
});
}
This makes sure that our TestBed gives us the mockDb instance of the DatabaseService instead of the actual instance of the Database service.
Now that the TestBed has been configured, we should be able to create our tests. This brings us to the ultimate question - what does the getContacts method from our mockDb return?
The answer is quite simple - whatever you want it to return. Of course, you want it to return the data you expect. In our case, we want it to return an array of string.
it('should return contacts', () => {
const testContacts = ['TEST 1', 'TEST 2'];
mockDb.getContacts.and.returnValue(testContacts);
expect(directoryService.contacts()).toEqual(testContacts);
});
Noticed the line that creates the return value for our getContacts method? We have full control on what our Database service returns and we know that the return value from that call should match the return of our DirectoryService's contacts method.
Now that we have understood how to test dependencies, a very interesting question arises. How do we test HTTP calls? What if instead of the DatabaseService, we were injecting HttpClient?
Let's do that on my next post.