Skip to main content

How to test a standalone pipe in Angular application

A standalone pipe doesn't have many differences comparing to 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 image we have the next 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);
}
}

As we see, it injects RootService, which should be mocked in unit tests.

It's possible to configure with the next code:

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 then the code would look like:

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

Live example

https://github.com/help-me-mom/ng-mocks/tree/master/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');

// 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');
});
});