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;
newthe class. - Argument order —
transform(value, ...args); the piped value is always first. - Impure pipes — mark
pure: falseonly 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.
Related guides
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).
Software Engineering Leader & Technical Author · Updated August 26, 2026