Skip to main content

How to mock pipes in Angular tests

A mock pipe in Angular tests can be created by MockPipe function. The second parameter of the function accepts a custom transform callback. The mock pipe has the identical interface as its source pipe, but all its methods are dummies.

To provide a mock pipe in a test, pass this source pipe into MockPipe function.

TestBed.configureTestingModule({
declarations: [
// for a single pipe
MockPipe(Pipe),

// a fake transform callback
MockPipe(Pipe, value => JSON.stringify(value)),

// for a set of pipe
...MockPipes(Pipe1, Pipe2),
],
});

A mock pipe has:

  • the same name
  • default transform is () => undefined to prevent problems with chaining
  • support for standalone pipes

Simple example

Let's imagine that in an Angular application TargetComponent depends on DependencyPipe pipe, and we would like to replace it with its mock pipe.

Usually a test looks like:

describe('Test', () => {
let component: TargetComponent;
let fixture: ComponentFixture<TargetComponent>;

beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
// our component for testing
TargetComponent,

// the annoying dependency
DependencyPipe,
],
});

fixture = TestBed.createComponent(TargetComponent);
component = fixture.componentInstance;
});
});

To create a mock pipe out of a pipe, simply pass the original pipe into MockPipe:

TestBed.configureTestingModule({
declarations: [
TargetComponent,

// profit
MockPipe(DependencyPipe, value => `mock:${value}`),
],
});

Or if we want to be like a pro, use MockBuilder, its .mock method and call MockRender:

describe('Test', () => {
beforeEach(() => {
return MockBuilder(TargetComponent, ItsModule)
// DependencyPipe is a declaration in ItsModule
.mock(DependencyPipe, value => `mock:${value}`);
});

it('should create', () => {
const fixture = MockRender(TargetComponent);
expect(fixture.point.componentInstance).toBeDefined();
expect(fixture.nativeElement.innerHTML).toContain('mock:foo');

// An instance of DependencyPipe from the fixture if we need it.
const pipe = ngMocks.findInstance(DependencyPipe);
expect(pipe).toBeDefined();
});
});

Standalone pipes

Since Angular 14, pipes can be implemented as a standalone declaration. ng-mocks detects and correctly mocks them. To mock a standalone pipe, you need to call MockPipe in imports:

TestBed.configureTestingModule({
imports: [
// for a single pipe
MockPipe(StandalonePipe),
],
declarations: [
// our component for testing
TargetComponent,
],
});

MockBuilder also supports and correctly works with standalone pipes.

Advanced example

An advanced example of mocking pipes in Angular tests. Please, pay attention to comments in the code.

https://github.com/help-me-mom/ng-mocks/blob/master/examples/MockPipe/test.spec.ts
// A fake transform function.
const fakeTransform = (...args: string[]) => JSON.stringify(args);

describe('MockPipe', () => {
// A spy, just in case if we want to verify
// how the pipe has been called.
const spy = jasmine.createSpy().and.callFake(fakeTransform);
// in case of jest
// const spy = jest.fn().mockImplementation(fakeTransform);

beforeEach(() => {
return (
MockBuilder(TargetComponent, ItsModule)
// DependencyPipe is a declaration in ItsModule
.mock(DependencyPipe, spy)
);
});

it('transforms values to json', () => {
const fixture = MockRender(TargetComponent);

expect(fixture.nativeElement.innerHTML).toEqual(
'<target>["foo"]</target>',
);

// Also we can find an instance of the pipe in
// the fixture if it is needed.
const pipe = ngMocks.findInstance(DependencyPipe);
expect(pipe.transform).toHaveBeenCalledWith('foo');
expect(pipe.transform).toHaveBeenCalledTimes(1);
});
});