Testing DI Functions in Angular
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!