InterviewsVector

Testing Angular Pipes with Jasmine & Karma: Pure, Dependency-Injecting, and In-Template

Quick answer

A pure Angular pipe is just a class with a transform method, so you don't need TestBed: instantiate it and assert on the return value — const pipe = new MyPipe(); expect(pipe.transform('abc')).toBe('Abc'). Use TestBed only when the pipe injects a dependency (configure it as a provider and inject the pipe), or when you want to test the pipe as used inside a component's template via a fixture.

Short answer: A pure pipe is just a class with a transform method, so you don't need TestBed — instantiate it and assert on the return value: const pipe = new MyPipe(); expect(pipe.transform('abc')).toBe('Abc'). Reach for TestBed only when the pipe injects a dependency or when you want to test it inside a component template.

Pipes are the easiest Angular building block to test — and interviewers use them to check whether you understand that a pipe is just a class. Most of the time you don't need Angular's testing machinery at all.

The pipe under test

import { Pipe, PipeTransform } from "@angular/core"
 
@Pipe({ name: "titleCaseWords", standalone: true })
export class TitleCaseWordsPipe implements PipeTransform {
  transform(input: string): string {
    if (!input) return ""
    return input.replace(
      /\w\S*/g,
      (w) => w[0].toUpperCase() + w.slice(1).toLowerCase()
    )
  }
}

1. Pure pipe — no TestBed

Because it's a plain class, new it and assert:

import { TitleCaseWordsPipe } from "./title-case-words.pipe"
 
describe("TitleCaseWordsPipe", () => {
  const pipe = new TitleCaseWordsPipe()
 
  it("is created", () => expect(pipe).toBeTruthy())
  it("title-cases a single word", () =>
    expect(pipe.transform("abc")).toBe("Abc"))
  it("title-cases every word", () =>
    expect(pipe.transform("abc def")).toBe("Abc Def"))
  it("handles empty input", () => expect(pipe.transform("")).toBe(""))
})

Fast, no fixtures, no detectChanges. This is the answer to "how would you test a pipe?" in an interview.

2. Parameterised pipes

transform takes the value first, then the template arguments (value | pipe:arg1:arg2):

transform(value: number, currency = "USD"): string { … }
// test:
expect(pipe.transform(5, "EUR")).toBe("€5.00")

3. A pipe that injects a dependency — use TestBed

When the pipe injects a service, register both in TestBed and inject the pipe so DI is wired:

import { TestBed } from "@angular/core/testing"
 
describe("GreetPipe", () => {
  let pipe: GreetPipe
 
  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [
        GreetPipe,
        { provide: LocaleService, useValue: { lang: () => "en" } }, // mock
      ],
    })
    pipe = TestBed.inject(GreetPipe)
  })
 
  it("greets in the active locale", () =>
    expect(pipe.transform("Sam")).toBe("Hello, Sam"))
})

4. Testing a pipe inside a template — host component + fixture

To verify the pipe as actually used, render a tiny host component and assert on the DOM:

import { Component } from "@angular/core"
import { TestBed } from "@angular/core/testing"
 
@Component({
  standalone: true,
  imports: [TitleCaseWordsPipe],
  template: `<p>{{ 'abc def' | titleCaseWords }}</p>`,
})
class HostComponent {}
 
it("renders through the template", () => {
  const fixture = TestBed.createComponent(HostComponent)
  fixture.detectChanges()
  expect(fixture.nativeElement.textContent).toContain("Abc Def")
})

Common interview traps

  • Reaching for TestBed on a pure pipe — unnecessary; new the class.
  • Argument ordertransform(value, ...args); the piped value is always first.
  • Impure pipes — mark pure: false only when the pipe must re-run on every change detection (it has real performance cost); test the transform the same way, but be aware of when it fires.
  • Forgetting detectChanges() — only relevant for the template/fixture approach, not the pure-class tests.

Sources

Key takeaways

  • Pure pipes need no TestBed — new the class and assert on transform(); it's fast and simple.
  • transform takes the value first, then any pipe arguments: transform(value, arg1, arg2).
  • For a pipe that injects a dependency, register it (and a mock dep) in TestBed and inject the pipe.
  • To test a pipe in context, render a host component with TestBed and assert on the rendered DOM.
  • Reserve fakeAsync/TestBed complexity for the cases that actually need it — not plain pure pipes.

Frequently asked questions

Do I need TestBed to test an Angular pipe?

No, not for a pure pipe. A pipe is a class implementing PipeTransform, so you can instantiate it directly and assert on transform()'s return value. TestBed is only needed when the pipe injects a dependency, or when you want to test it rendered inside a component template.

How do I test a pipe that has constructor dependencies?

Configure TestBed with the pipe and its dependency (usually a mock/stub) as providers, then use TestBed.inject(MyPipe) to get an instance with dependencies wired, and assert on transform().

How do I test a pipe used inside a component template?

Create a small host component that uses the pipe in its template, declare/import both in TestBed, create a fixture, call detectChanges(), and assert on the rendered DOM (e.g. fixture.nativeElement.textContent).

By Mohammad Wasi

Software Engineering Leader & Technical Author · Updated August 26, 2026


Related Posts