Skip to main content

How to test a standalone pipe in Angular

A standalone pipe is not very different from a regular pipe. It cannot import any dependencies, it can only inject root providers. In order to mock root providers, MockBuilder can be used.

Let's imagine we have the following standalone pipe:

@Pipe({
name: 'standalone',
standalone: true,
})
class StandalonePipe implements PipeTransform {
constructor(public readonly rootService: RootService) {}

transform(value: string): string {
return this.rootService.trigger(value);
}
}

It injects RootService, which should be mocked in unit tests.

You can configure it like this:

beforeEach(() => {
return MockBuilder(StandalonePipe);
});

Now all root dependencies of StandalonePipe are mocks, and the properties, methods, injections of the pipe are available for testing.

If you need to keep a dependency, simply call .keep with it. For example, if we wanted to keep RootService, the code would look like this:

beforeEach(() => {
return MockBuilder(StandalonePipe).keep(RootService);
});

Live example

https://github.com/help-me-mom/ng-mocks/tree/main/examples/TestStandalonePipe/test.spec.ts
import {
Injectable,
Pipe,
PipeTransform,
} from '@angular/core';

import {
MockBuilder,
MockInstance,
MockRender,
ngMocks,
} from 'ng-mocks';

// A root service we want to mock.
@Injectable({
providedIn: 'root',
})
class RootService {
trigger(name: string) {
// does something very cool

return name;
}
}

// A standalone pipe we are going to test.
@Pipe({
name: 'standalone',
standalone: true,
})
class StandalonePipe implements PipeTransform {
constructor(public readonly rootService: RootService) {}

transform(value: string): string {
return this.rootService.trigger(value);
}
}

describe('TestStandalonePipe', () => {
// It creates a context for mocks which will be reset after each test.
MockInstance.scope();

beforeEach(() => {
return MockBuilder(StandalonePipe);
});

it('renders dependencies', () => {
// Customizing what RootService does.
MockInstance(
RootService,
'trigger',
jasmine.createSpy().and.returnValue('mock'),
// or in case of jest
// jest.fn().mockReturnValue('mock'),
);

// Rendering the pipe.
const fixture = MockRender(StandalonePipe, {
$implicit: 'test',
});

// Asserting that StandalonePipe calls RootService.trigger.
const rootService = ngMocks.findInstance(RootService);
// It's possible because of autoSpy.
expect(rootService.trigger).toHaveBeenCalledWith('test');

// Asserting that StandalonePipe has rendered the result of the RootService
expect(ngMocks.formatText(fixture)).toEqual('mock');
});
});