Angular Pipes: Integrated Unit Testing
Tags: angular, testing
Published: 2019-05-30 12:10:09

---
title: Angular Pipes: Integrated Unit Testing
published: true
tags: Angular,Testing
canonical_url: https://www.amadousall.com/angular-pipes-integrated-unit-testing/
---

 ![Angular Pipes: Integrated Unit Testing](https://www.amadousall.com/content/images/2018/02/cover-2.png)

In my [previous blog post](https://dev.to/ahasall/angular-pipes-isolated-unit-testing-38ga-temp-slug-1816279), we learned that there were two ways to unit test Angular pipes:

- Isolated tests (without TestBed)
- Integrated tests (with TestBed)

But we put the focus on isolated tests. I this article, we are going to switch our focus on how to write integrated unit tests for Angular pipes.

We talk about integrated unit testing when we are testing the pipe in the same condition that it will be used at runtime. This means that we will test it when used inside an Angular component's template.

## The Pipe Under Test

In case, you didn't read my previous blog post, here is the code of the pipe we are going to test. It is a simple pipe that transforms an array to its mean.

![Angular Pipes: Integrated Unit Testing](https://www.amadousall.com/content/images/2018/02/mean.pipe.ts-1.png)

1. Implement the `PipeTransform` interface.
2. Return the mean of the array of numbers.

The full source code of this pipe can be found at the end of the article or [here](https://gist.github.com/amadousalldotcom/9bcbbc5ee1745bf10c890a5c423bd477).

## We Need a Host Component

Because we want to write integrated tests for our pipe, we need a component that hosts our pipe. A host component is like any other Angular component. There is nothing specific about it. It is just a way to use the pipe in an Angular component's template.

The code for the host component is straightforward:

![Angular Pipes: Integrated Unit Testing](https://www.amadousall.com/content/images/2018/02/host-component.png)

1. Define property that holds the values to be passed to the pipe
2. Display the result of the transformation of those values through the pipe.

## Setting Up the Integrated Tests!

![Angular Pipes: Integrated Unit Testing](https://www.amadousall.com/content/images/2018/02/tests-setup.png)

1. `TestBed.configureTestingModule`, as its name implies, allows us to create a specific Angular module for testing purposes. It accepts pretty much the same parameters as the `NgModule` decorator.
2. Notice that we wrap the body of our first `beforeEach` inside a special Angular zone. We do so by calling the `async` function, one of the many Angular testing utilities. We need this because `TestBet.compileComponents` is asynchronous. So this ensures that our component's template is compiled beforehand (although technically this is not necessary in this example because our template is inlined).
3. A `ComponentFixture` is a wrapper around our host component. It allows us to interact with the environment of our component like its change detection or its injector.
4. The fixture is returned by `TestBed.createComponent`.
5. From the fixture, we can get the `DebugElement`. The `DebugElement` is a wrapper around our component's HTML element. It provides more functionality than the native `HTMLElement`.
6. We can also get the real instance of our component from the fixture.

We made sure that our fixture can be properly instantiated. Now we can start writing real expectations.

## The Actual Tests

![Angular Pipes: Integrated Unit Testing](https://www.amadousall.com/content/images/2018/02/tests.png)

1. We start by updating the `values` property of our component and we call `fixture.detectChanges`. `fixture.detectChanges` kicks off change detection for our component. It is necessary if we want our template to reflect the changes we made to the component class.
2. Next, we use `debugElement.query` passing it a predicate `By.css('div')`. This allows us to target the div element by using its CSS selector.
3. From there, we can get the native `HTMLDivElement`.
4. Then we can write our expectations.

The full source code of this pipe can be found at the end of the article or [here](https://gist.github.com/amadousalldotcom/bcb219ccba19283c08e69198839aedac)

In this article, we learned how to write integrated unit tests for our Angular pipes. The setup for this kind of is more complicated than for isolated unit tests. There are also more concepts involved because we need to use Angular testing utilities. But the effort is forth it as integrated unit tests can help us detect bugs that isolated tests cannot reveal.

Thank you very much for reading!

* * *

## Listing
## mean.pipe.ts
```typescript
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'mean'
})
export class MeanPipe implements PipeTransform {

  transform(value: number[]): number {
    if (!Array.isArray(value)) {
      return value;
    }
    if (value.length === 0) {
      return undefined;
    }
    const sum = value.reduce((n: number, m: number) => n + m, 0);
    return  sum / value.length;
  }
}
```
## mean.pipe.integrated.spec.ts
```typescript
import { MeanPipe } from './mean.pipe';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { Component, DebugElement } from '@angular/core';
import { By } from '@angular/platform-browser';


@Component({
  template: '<div> {{ values | mean }}</div>'
})
export class MeanPipeHostComponent {
  values: number[];
}

describe('MeanPipe inside a Component', () => {
  beforeEach(async(() => {
    TestBed
      .configureTestingModule({
        declarations: [MeanPipe, MeanPipeHostComponent]
      })
      .compileComponents();
  }));

  let fixture: ComponentFixture<MeanPipeHostComponent>;
  let debugElement: DebugElement;

  let component: MeanPipeHostComponent;

  beforeEach(() => {
    fixture = TestBed.createComponent(MeanPipeHostComponent);
    debugElement = fixture.debugElement;
    component = fixture.componentInstance;
  });

  it('should create an instance', () => {
    expect(fixture).toBeTruthy();
  });

  it('should display 1', () => {
    component.values = [1, 1];
    fixture.detectChanges();

    const div: HTMLDivElement = debugElement
      .query(By.css('div'))
      .nativeElement;

    expect(div.textContent.trim()).toEqual('1');
  });

  it('should display 0', () => {
    component.values = [1, -1];
    fixture.detectChanges();

    const div: HTMLDivElement = debugElement
      .query(By.css('div'))
      .nativeElement;

    expect(div.textContent.trim()).toEqual('0');
  });

  it('should display nothing', () => {
    component.values = [];
    fixture.detectChanges();

    const div: HTMLDivElement = debugElement
      .query(By.css('div'))
      .nativeElement;

    expect(div.textContent.trim()).toEqual('');
  });
});
```