DEV Community

Cover image for Angular Unit Testing inject() without TestBed
Elvijs
Elvijs

Posted on

Angular Unit Testing inject() without TestBed

This post should serve as a reference.

// src/app/foo.component.ts import { CommonModule } from '@angular/common' import { ChangeDetectionStrategy, Component, inject, signal, } from '@angular/core' import { User, UserService } from './services/user.service' @Component({ selector: 'foo-component', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: ` <input (input)="input.set($any($event.target).value)" [value]="input()" /> <button (click)="search()">Search</button> <pre>{{ user() | json }}</pre> <pre>{{ error() | json }}</pre> `, }) export class FooComponent { userService = inject(UserService) input = signal('') user = signal<User | null>(null) error = signal<string | null>(null) async search() { const [user, error] = await this.userService.search(this.input()) this.user.set(user) this.error.set(error) } } 
Enter fullscreen mode Exit fullscreen mode
// src/app/services/user.service.ts import { Injectable } from '@angular/core' interface Response { id: number name: string email: string } export interface User { id: number email: string } @Injectable({ providedIn: 'root' }) export class UserService { #url = 'https://jsonplaceholder.typicode.com/users/' async search(userId: string): Promise<[User, null] | [null, string]> { try { const response = await fetch(this.#url + userId) if (!response.ok) { throw new Error() } const { id, email } = (await response.json()) as Response const user: User = { id, email } return [user, null] } catch (_) { return [null, 'Failed to fetch user'] } } } 
Enter fullscreen mode Exit fullscreen mode
// src/app/foo.component.test.ts import { Injector } from '@angular/core' import { FooComponent } from './foo.component' import { UserService } from './services/user.service' const mockUserService = { search: jest.fn().mockImplementation((id: string) => { if (id === '1') { return Promise.resolve([{ id: 1, email: 'john@example.com' }, null]) } else { return Promise.resolve([null, 'Failed to fetch user']) } }), } describe('FooComponent', () => { const component: FooComponent = Injector.create({ providers: [ { provide: FooComponent }, { provide: UserService, useValue: mockUserService }, ], }).get(FooComponent) it('search(): success', async () => { component.input.set('1') await component.search() expect(component.user()).toEqual({ email: 'john@example.com', id: 1 }) expect(component.error()).toEqual(null) }) it('search(): error', async () => { component.input.set('?') await component.search() expect(component.user()).toEqual(null) expect(component.error()).toEqual('Failed to fetch user') }) }) 
Enter fullscreen mode Exit fullscreen mode
// src/app/services/user.service.test.ts import { UserService } from './user.service' global.fetch = jest.fn(url => { if (url.endsWith('1')) { return Promise.resolve({ ok: true, json: () => Promise.resolve({ id: 1, email: 'test@example.com' }), }) } else { return Promise.resolve({ ok: false }) } }) as jest.Mock describe('UserService', () => { const service: UserService = new UserService() it('search(): success', async () => { const [user, error] = await service.search('1') expect(user).toEqual({ id: 1, email: 'test@example.com' }) expect(error).toEqual(null) }) it('search(): error', async () => { const [user, error] = await service.search('?') expect(user).toEqual(null) expect(error).toEqual('Failed to fetch user') }) }) 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)