Back to the homepage
Angular

ng mocks – what is it all about?

Everyone who has written tests (not necessarily in Angular) knows that mocking the dependencies of a test item can sometimes be a pain in the neck. It depends, of course, on the quality and complexity of the code in our project. Let’s look at the following example:

An overflow of such dependencies can effectively delay us from moving on to writing proper test cases. So why not make life easier by shortening and simplifying the test module configuration?

Let’s take a look at the ng-mocks library, which is intended to help us in the areas mentioned above. It supports Angular from version 5 upwards (it also works with Ivy in newer versions) and works with both jest and jasmine – so its compatibility is pretty good. 

So – is it worth installing another library for your project? In this article, I will try to help you answer this question.

Disclaimer regarding the code

All snippets are written using the SIFERS (Simple Injectable Functions Explicitly Returning State) architecture. Not to stray from the topic of the article – for those of you who have never used SIFERS before, I recommend a great article by Moshe Kolodny.

An approach using helpers

In its simplest form, the ng-mocks library comes with a set of helper functions that facilitate the use of the Angular TestBed class. While this class doesn’t seem difficult to use, things get more complicated the more complicated our dependency tree is. This effectively prolongs the number of mocks we need to prepare to write test cases and the upcoming hour we will likely spend with red messages like “NullInjectorError: No provider for XXX” anyways.

Let’s see what good things ng-mocks offers us:

MockComponent

The function creates a mock component with the given type. It will keep the original interface, which includes Inputs, Outputs, selector, transclusion support and a few other properties. However, its entire implementation will be empty.

MockModule

Analogically, except that it creates a mock of the indicated module. As with the component, it will reflect the interface but the implementation will be empty. What’s more, it will mock all intermediate dependencies imported by the given module – in most cases, we won’t need to care about them at all.

MockProvider

The function allows you to mock the provider and accepts Servers and InjectionTokens. It includes different ways to define a provider in a standard way.

MockService, MockDirective and MockPipe

These functions allow you to mock elements with types indicated in the helper name. More detailed descriptions with examples can be found in the documentation of the library (here). 

As you can see the purpose of the helpers is quite intuitive. Let’s look at the example code below. ng-mocks has not been used yet. The code presented in this article can be downloaded from my GitHub – you can find the link at the end of the article. 

Let’s apply the described helpers to the above example. We will get the following code:

The first conspicuous thing is a much clearer syntax. Is this an added value? In very small projects the difference will be purely academic, so not necessarily. On the other hand, as the scale and complexity increase, it can already be quite an asset. Especially if we return to the tests we wrote in the past after a long time or work with tests written by another programmer. And that’s not all yet.

Use of MockBuilder

Let me quote the documentation of the library – in free translation “MockBuilder is the easiest way to mock virtually anything”. So here we go with Mockbuilder.

MockBuilder

It is a function for mocking various elements written in the form of a fluent API, i.e. a chain of methods with – as Uncle Bob described it – meaningful names (if you don’t know who Uncle Bob is make sure to check it out later tonight!). It can take as input two optional arguments. The first one specifies the element that should not be docked (it can be a component or InjectionToken), while the second one specifies the module to be docked along with all dependencies. These arguments can be used together or individually, or you can not specify them at all.

What’s more, this function creates a convenient and readable block of code that basically exhausts the topic of preparing the environment and allows us to focus on writing specific test cases. Anyway, let the code speak – let’s try to rebuild the previous section:

As you can see, MockBuilder does much of the work for us. The function itself is well described in the documentation, so I won’t duplicate that information here. Suffice to say that even when all else fails you can still invoke the good old TestBed class:

MockRender

As the name suggests, this function is used to render components. It uses the inside angular method TestBed.createComponent, but what is worth noticing is that it returns a different type from its original: MockedComponentFixture<Component>. For the inquisitive – the purpose of using such an indirect construction is explained by the library’s developers here.

MockInstance

This function makes it easier to prepare and adjust the shape of a class instance, which is especially useful when creating spies.

Let’s look at an example of using such a function:

Note that the last argument can be used to easily create a spy object:

So we get another tool, which for a programmer can turn out to be useful. For more, I refer you to the documentation.

ngMocks

The name above is a namespace aggregating numerous helpers of various uses. In order not to prolong the article once again I will refer you to the documentation of the library.

Advantages

Let’s try to summarize this library. We get a package of function-helpers that improve the “classic” approach based on the TestBed class. Furthermore, we have the MockBuilder function, which gives a very wide range of possibilities and limits the use of TestBed only to special cases. We have reduced the amount of code configuring the environment and automated the creation of mocks, which will allow us to focus on the test code. And that is all that matters. 

The answer is obvious, and – unless our project is significantly small – my opinion will be short. It’s worth it.

Summary

All the code examples shown above were part of a sample app, prepared for this article. The entire code can be downloaded from my github, here I will only show the body of the setup() function – as the specific test cases are already identical in each case.

Without ng-mocks

Component

Pipe

Service

Ng-mocks – only helpers

Component

Pipe

Service

Ng-mocks using MockBuilder

Component

Pipe

Service

Dear readers, now is the time to express your own opinion. If you are not familiar with this library, I strongly encourage you to download it and try it out. Enjoy your coding!

About the author

Łukasz Joorewicz

Lukasz has been working with Angular for years, but he is making his debut in writing articles. In his free time, he is a drummer in a rock band and recently became an avid cyclist. He likes to get away from his laptop from time to time.

Do you want to write articles for our blog together with us?
Join us and create valuable content for Angular fans with Angular.love!

Leave a Reply

Your email address will not be published. Required fields are marked *