Unit testing is a key aspect of modern web development, ensuring the individual components of your Angular application function as expected. In this guide, we'll explore the integrated testing environment provided by Jasmine and Karma, which are used in Angular applications to create and execute unit tests.
Jasmine is a behavior-driven development framework that provides a syntax for writing tests. It includes features like spies, assertions, and test doubles to help verify that your code behaves as expected.
Karma is a test runner that allows you to execute JavaScript code in multiple real browsers, providing a robust testing environment. It enables you to run your Jasmine tests automatically or on a continuous integration pipeline.
If you start with a standard Angular application created using the Angular CLI, Jasmine and Karma come preconfigured for you. However, if you need to set it up manually, follow these steps:
Install Angular CLI:
npm install -g @angular/cli
Create a New Angular Project:
ng new my-angular-app cd my-angular-app
Default Testing Dependencies:
Angular CLI automatically installs Jasmine and Karma. You’ll find them in the package.json
under devDependencies
.
Run Tests: Launch the test runner by executing:
ng test
It will start Karma and open your default browser, running the tests in real-time.
Let’s write a simple unit test for a component in Angular. Assume you have a component named CalculatorComponent
with a method add(a: number, b: number)
that sums two numbers.
import { Component } from '@angular/core'; @Component({ selector: 'app-calculator', template: `<div></div>`, }) export class CalculatorComponent { add(a: number, b: number): number { return a + b; } }
Create a new file named calculator.component.spec.ts
and add the following test:
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { CalculatorComponent } from './calculator.component'; describe('CalculatorComponent', () => { let component: CalculatorComponent; let fixture: ComponentFixture<CalculatorComponent>; beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [CalculatorComponent], }).compileComponents(); fixture = TestBed.createComponent(CalculatorComponent); component = fixture.componentInstance; }); it('should add two numbers correctly', () => { const result = component.add(2, 3); expect(result).toEqual(5); }); });
CalculatorComponent
.CalculatorComponent
.add
method returns the expected result.One of Jasmine’s most powerful features is the ability to create spies, enabling you to track interactions with functions. Consider a scenario where CalculatorComponent
calls a service that logs operations.
export class LoggerService { log(message: string) { console.log(message); } }
import { Component } from '@angular/core'; import { LoggerService } from './logger.service'; @Component({ selector: 'app-calculator', template: `<div></div>`, }) export class CalculatorComponent { constructor(private logger: LoggerService) {} add(a: number, b: number): number { const result = a + b; this.logger.log(`Added ${a} and ${b}: ${result}`); return result; } }
Here’s how you can create a spy for the LoggerService
in your tests:
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { CalculatorComponent } from './calculator.component'; import { LoggerService } from './logger.service'; describe('CalculatorComponent with Spies', () => { let component: CalculatorComponent; let fixture: ComponentFixture<CalculatorComponent>; let loggerServiceSpy: jasmine.SpyObj<LoggerService>; beforeEach(async () => { loggerServiceSpy = jasmine.createSpyObj('LoggerService', ['log']); await TestBed.configureTestingModule({ declarations: [CalculatorComponent], providers: [{ provide: LoggerService, useValue: loggerServiceSpy }], }).compileComponents(); fixture = TestBed.createComponent(CalculatorComponent); component = fixture.componentInstance; }); it('should log addition operation', () => { component.add(5, 3); expect(loggerServiceSpy.log).toHaveBeenCalledWith('Added 5 and 3: 8'); }); });
LoggerService
with a method log
.CalculatorComponent
is created.log
method was called with the correct parameters.Through these examples, we’ve built a solid foundation for unit testing in Angular applications. Remember, consistent unit testing increases code reliability and maintainability and is a vital practice for any Angular developer.
24/10/2024 | Angular
24/10/2024 | Angular
24/10/2024 | Angular
24/10/2024 | Angular
24/10/2024 | Angular
24/10/2024 | Angular
24/10/2024 | Angular
24/10/2024 | Angular