Testing DI Functions in Angular

Netanel Basal
Netanel Basal
Published in
2 min readDec 11, 2022

--

A new static method named runInInjectionContext has been added to TestBed in Angular v15.1.0-next.0 to make testing inject() easier. The runInInjectionContext function works similarly to the runInContext function. Let’s say we have a function that uses the http module to fetch users:

export function getUsers() {
return inject(HttpClient).get<User[]>('users');
}

We can test it by passing the getUsers function to TestBed.runInInjectionContext:

import { TestBed } from '@angular/core/testing';
import {
HttpClientTestingModule,
HttpTestingController,
} from '@angular/common/http/testing';

describe('Users', () => {

it('should fetch users', () => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
});

const controller = TestBed.inject(HttpTestingController);

TestBed.runInInjectionContext(getUsers).subscribe((users) => {
expect(users.length).toBe(1);
});

controller.expectOne('users').flush([{ id: 1 }]);
});

});

Let’s see one more example when using an InjectionToken:

export const FOO = new InjectionToken('FOO', {
providedIn: 'root',
factory() {
return 'foo';
},
});

export function getFoo() {
return inject(FOO);
}

Let’s say we want to test the getFoo function but override what FOO returns:

import { TestBed } from '@angular/core/testing';

describe('Foo', () => {

it('should get 🔥', () => {
TestBed.overrideProvider(FOO, { useValue: '🔥' });
const result = TestBed.runInInjectionContext(getFoo);
expect(result).toEqual('🔥');
});

it('should get 🙌', () => {
TestBed.overrideProvider(FOO, { useValue: '🙌' });
const result = TestBed.runInInjectionContext(getFoo);
expect(result).toEqual('🙌');
});

});

It will also work with fakeAsync. Let’s say we have a BAR provider that returns a promise:

import { TestBed, fakeAsync } from '@angular/core/testing';

describe('Bar', () => {

it('should work with fakeAsync', fakeAsync(() => {
TestBed.overrideProvider(BAR, { useValue: Promise.resolve('😄') });
let result = '';

TestBed.runInInjectionContext(getBar).then((v) => {
result = v;
});

flushMicrotasks();
expect(result).toEqual('😄');
}));

});

In earlier versions you can use the EnvironmentInjector to test it:

TestBed.inject(EnvironmentInjector).runInContext(getUsers);

Follow me on Medium or Twitter to read more about Angular and JS!

--

--

A FrontEnd Tech Lead, blogger, and open source maintainer. The founder of ngneat, husband and father.