Skip to main content

How to customize mocks in Angular tests

ng-mocks providers vast ways how to mock declarations, providers and classic classes. The goal of this article is to explain purpose of every way and to try to describe it in details.

ngMocks.defaultMock

ngMocks.defaultMock - is useful to provide default mock behavior for declarations, services and tokens in the entire test suites. For example, we have a service with a property that is an observable stream. In tests, we would like to avoid failures like Cannot read property 'subscribe' of undefined, when we are mocking the service.

It can be done like that:

src/test.ts
ngMocks.defaultMock(MyService, () => ({
stream$: EMPTY,
}));

Profit, now mocks of MyService will have an EMPTY stream in the stream$ property and all its subscribes will not fail anymore. More information you can find in the related section about ngMocks.defaultMock.

MockProvider

MockProvider - is useful when we are configuring TestBed.configureTestingModule and would like to mock a service or a token.

TestBed.configureTestingModule({
providers: [MockProvider(MyService)],
});

Now, in related tests, MyService will be replaced with its mock object where its stream$ property is the EMPTY observable stream due to the customization in the previous section about ngMocks.defaultMock.

Furthermore, we can pass a custom slice as the second parameter for extra customization. It takes the effect after all customizations defined in ngMocks.defaultMock.

TestBed.configureTestingModule({
providers: [
MockProvider(MyService, {
stream$: throwError(new Error('broken stream')),
}),
],
});

This will override the stream$ property, and now, all its subscribes will get an error in the related tests. More information you can find in the section about MockProvider.

MockInstance

MockInstance - is useful when we need to customize behavior of a declaration or provider in a particular test. For example, we want the stream$ to emit something.

note

MockProvider should be called before MockRender or TestBed.createComponent.

it('test', () => {
const stream$ = new Subject();
MockInstance(MyService, () => ({
stream$,
}));
const fixture = MockRender(MyComponent);

stream$.next(true); // a mock emit.
fixture.detectChanges();
});

MockInstance is the latest in the sequence of customizing behavior, and will be applied after MockProvider, MockBuilder.mock and ngMocks.defaultMock.

More information you can find in the related section about MockInstance.

MockService

MockService - is useful when we need to create a mock instance of a class, and the class do not belong to declarations or providers.

A mock object produced by MockService is based on its original class, and provides:

  • all methods are dummies
  • all properties have been linked via getters and setters (might not work in some cases, use ngMocks.stub then)
  • respects auto spy environment

For example, we have a mock component which real copy has an inputElement property with an instance of HTMLInputElement, and some other component tries to focus on it like this.viewChildRef.inputElement.focus(), and another one tries to blur, etc. But, in our tests, these calls are just side effects, we would like to suppress them.

That is the case where MockService shines. Because this customization may be useful for other tests too, let's define it via ngMocks.defaultMock. Also, its optional second parameter accepts a slice of the instance for extra customization.

src/test.ts
ngMocks.defaultMock(MyComponent, () => ({
inputElement: MockService(HTMLInputElement, {
tagName: 'DIV',
}),
}));

Profit. Now, every time when a mock object of MyComponent is needed, its inputElement will be a mock object of HTMLInputElement, and its consumers can safely call .focus(), .blur() along with other methods.

Recap

To recap the section:

  • ngMocks.defaultMock - customize mocks of declarations and providers globally.
  • MockProvider - customizes mocks of declarations and providers in suites.
  • MockInstance - customizes mocks of declarations and providers in tests.
  • MockService - creates mock objects out of any classes.

The priority of customization is: