NashTech Insights

Unit Testing and Test-Driven Development (TDD) in Angular

Alka Vats
Alka Vats
Table of Contents

Introduction

Unit testing and Test-Driven Development (TDD) are essential practices for building robust and reliable Angular applications. Unit tests verify the correctness of individual units of code, such as components, services, and directives, in isolation. TDD is an approach that emphasizes writing tests before writing the actual code, ensuring that the code meets the desired requirements. This blog will explore unit testing and TDD in Angular, along with practical example

If you want to learn about the testing features of angular, you can refer here.

Why Unit Testing and TDD in Angular?

Unit testing and TDD offer several benefits when developing Angular applications:
  1. Code Reliability: Unit tests help detect bugs and errors early in the development process, ensuring that code behaves as expected and minimizing potential issues.
  2. Refactoring Safety: Having comprehensive unit tests provides confidence when refactoring code, as tests serve as a safety net to catch any regressions.
  3. Faster Debugging: When a test fails, it allows developers to pinpoint the exact issue quickly, simplifying debugging and reducing the time spent on bug fixing.
  4. Continuous Integration: Automated unit tests are a crucial part of a continuous integration process, enabling continuous delivery and faster feedback cycles.

Setting Up Unit Testing in Angular

Angular comes with a built-in testing framework based on Karma and Jasmine, making it easy to set up and execute unit tests.

Step 1: Create a New Angular Project

If you haven’t created an Angular project yet, use Angular CLI to create a new project:

ng new angular-testing-example
cd angular-testing-example

Step 2: Writing a Simple Unit Test

Let’s write a simple unit test for a service that performs basic arithmetic operations.

Step 2.1: Generate the Service

Create a new service called calculator using Angular CLI:

ng generate service calculator
Step 2.2: Implement the Service

Open the calculator.service.ts file and implement the arithmetic operations:

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class CalculatorService {
  add(a: number, b: number): number {
    return a + b;
  }

  subtract(a: number, b: number): number {
    return a - b;
  }

  multiply(a: number, b: number): number {
    return a * b;
  }

  divide(a: number, b: number): number {
    if (b === 0) {
      throw new Error('Division by zero is not allowed.');
    }
    return a / b;
  }
}
Step 2.3: Write the Unit Test

Create a new file calculator.service.spec.ts in the same directory as calculator.service.ts. This is where the unit tests for the CalculatorService will reside.

import { TestBed } from '@angular/core/testing';
import { CalculatorService } from './calculator.service';

describe('CalculatorService', () => {
  let service: CalculatorService;

  beforeEach(() => {
    TestBed.configureTestingModule({});
    service = TestBed.inject(CalculatorService);
  });

  it('should be created', () => {
    expect(service).toBeTruthy();
  });

  it('should add two numbers', () => {
    expect(service.add(2, 3)).toEqual(5);
  });

  it('should subtract two numbers', () => {
    expect(service.subtract(5, 3)).toEqual(2);
  });

  it('should multiply two numbers', () => {
    expect(service.multiply(2, 3)).toEqual(6);
  });

  it('should divide two numbers', () => {
    expect(service.divide(6, 3)).toEqual(2);
  });

  it('should throw an error when dividing by zero', () => {
    expect(() => service.divide(5, 0)).toThrowError('Division by zero is not allowed.');
  });
});
Step 2.4: Run the Unit Tests

Execute the unit tests using the Angular CLI:

ng test

The tests should pass, confirming that the CalculatorService is functioning as expected.

Test-Driven Development (TDD) in Angular

Test-Driven Development (TDD) is an approach where you write tests before writing the actual code. The TDD process follows three steps:

  1. Write a Test: Start by writing a test that defines the behavior or functionality you want to implement.
  2. Run the Test: Run the test and observe it failing, as the functionality has not been implemented yet.
  3. Write the Code: Write the code necessary to make the test pass.

Example: TDD for a Simple Angular Component

Let’s follow the TDD approach to create a simple Angular component that displays a message.

Step 1: Write a Test

Create a new file message.component.spec.ts in the same directory as message.component.ts (if using Angular CLI, it should already create the test file when you generate the component).

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MessageComponent } from './message.component';

describe('MessageComponent', () => {
  let component: MessageComponent;
  let fixture: ComponentFixture<MessageComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [MessageComponent],
    }).compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(MessageComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('should display the correct message', () => {
    const message = 'Hello, World!';
    component.message = message;
    fixture.detectChanges();
    const compiled = fixture.nativeElement;
    expect(compiled.querySelector('p').textContent).toContain(message);
  });
});
Step 2: Run the Test

Running the test at this stage should result in a failure since the component has not been implemented yet.

Step 3: Write the Code

Now, let’s implement the MessageComponent.

import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-message',
  template: '<p>{{ message }}</p>',
})
export class MessageComponent {
  @Input() message = '';
}
Step 4: Run the Test Again

Running the test after implementing the component should now pass successfully.

Conclusion

Unit testing and Test-Driven Development (TDD) are crucial practices for developing reliable and maintainable Angular applications. In this blog, we explored how to set up unit testing in Angular using Jasmine and Karma. We also discussed the TDD approach, which involves writing tests before writing the actual code.

By writing comprehensive unit tests and following the TDD approach, you can ensure that your Angular application behaves as expected and is less prone to errors and regressions. Adopting unit testing and TDD as part of your development workflow can greatly improve the quality and reliability of your Angular applications. Happy testing and coding in Angular!

Finally, for more such posts, please follow our LinkedIn page- FrontEnd Competency.

Alka Vats

Alka Vats

Alka Vats is a Software Consultant at Nashtech. She is passionate about web development. She is recognized as a good team player, a dedicated and responsible professional, and a technology enthusiast. She is a quick learner & curious to learn new technologies. Her hobbies include reading books, watching movies, and traveling.

Leave a Comment

Your email address will not be published. Required fields are marked *

Suggested Article

%d bloggers like this: