Login Register
Code2night
  • Home
  • Blog Archive
  • Learn
    • Tutorials
    • Videos
  • Interview Q&A
  • Languages
    • Angular
    • Angular js
    • Asp.net Core
    • C
    • C#
    • DotNet
    • HTML/CSS
    • Java
    • JavaScript
    • Node.js
    • Python
    • React
    • Security
    • SQL Server
    • TypeScript
  • Post Blog
  • Tools
    • JSON Beautifier
    • HTML Beautifier
    • XML Beautifier
    • CSS Beautifier
    • JS Beautifier
    • PDF Editor
    • Word Counter
    • Base64 Encode/Decode
    • Diff Checker
    • JSON to CSV
    • Password Generator
    • SEO Analyzer
    • Background Remover
  1. Home
  2. Blog
  3. Angular
  4. Mastering Angular Unit Testing with Jasmine and Karma: A Comprehensive Guide

Mastering Angular Unit Testing with Jasmine and Karma: A Comprehensive Guide

Date- Mar 25,2026

0

angular jasmine

Overview

Unit testing is a software testing methodology that focuses on verifying individual components of code to ensure they function as expected. In the context of Angular, it allows developers to test components, services, and other pieces of the application in isolation. This practice is vital for catching bugs early in the development process, improving code quality, and facilitating easier refactoring.

The combination of Jasmine and Karma provides a comprehensive testing framework for Angular applications. Jasmine is a behavior-driven development framework for testing JavaScript code, while Karma acts as a test runner that executes the tests in real browsers. Together, they allow developers to write clear, readable tests and run them automatically across different environments, ensuring consistent results.

Real-world use cases for unit testing in Angular include validating user input in forms, checking the logic in services, and ensuring that components render the expected output based on the given inputs. By incorporating unit tests into your development process, you can significantly reduce the number of bugs and improve the overall quality of your application.

Prerequisites

  • Understanding of Angular: Familiarity with Angular framework concepts like components, services, and modules is essential.
  • Basic knowledge of TypeScript: Since Angular is built with TypeScript, understanding its syntax and features is necessary for writing tests.
  • Familiarity with JavaScript testing concepts: Knowing the fundamentals of testing in JavaScript will help you grasp Jasmine and Karma better.

Setting Up Jasmine and Karma

To begin unit testing in Angular, you first need to set up Jasmine and Karma in your Angular project. Angular CLI comes with built-in support for both tools, making the setup process straightforward. When creating a new Angular project, the CLI automatically configures Jasmine and Karma. However, if you need to configure them manually, you can do so by following these steps:

ng new my-angular-app --skip-install

This command creates a new Angular project without installing dependencies. Next, navigate to your project directory:

cd my-angular-app

Now, install the dependencies:

npm install

Once the installation is complete, you will find a karma.conf.js file and a tsconfig.spec.json file in your project. The karma.conf.js file contains the configuration for Karma, including the frameworks used (like Jasmine), the files to include, and the browsers to test on.

Example of karma.conf.js

module.exports = function(config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular-devkit/build-angular'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-coverage'),
      require('@angular-devkit/build-angular/plugins/karma')
    ],
    client: {
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    coverageReporter: {
      dir: require('path').join(__dirname, './coverage/my-angular-app'),
      subdir: '.',
      reporters: [{ type: 'html' }, { type: 'text-summary' }]
    },
    reporters: ['progress', 'coverage'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false,
    restartOnFileChange: true
  });
};

This configuration sets up Karma to use Jasmine for testing, includes the Angular testing framework, and specifies Chrome as the browser for running tests. The coverage reporter is also configured to generate coverage reports after the tests run.

Writing Your First Unit Test

With Jasmine and Karma configured, you can start writing your first unit test. Let’s create a simple Angular service and write a test for it. Start by generating a service using the Angular CLI:

ng generate service example

This creates an example.service.ts file in your project. Here’s a simple service that performs addition:

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

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

This service has a single method, add, which takes two numbers and returns their sum. Next, create a test file named example.service.spec.ts in the same directory:

import { TestBed } from '@angular/core/testing';
import { ExampleService } from './example.service';

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

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

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

This test suite uses Jasmine’s describe function to group related tests. Within the suite, the beforeEach function sets up the testing module and injects the ExampleService instance. Finally, the it function defines a test case to verify that the add method correctly adds two numbers.

Running the Tests

To execute your tests, simply run:

ng test

This command launches the Karma test runner, which opens a browser and displays the test results. If your test passes, you will see a green checkmark; if it fails, you will see a red cross along with an error message.

Testing Angular Components

Unit testing Angular components involves testing their behavior, view rendering, and interaction with services. A typical component contains a template, styles, and logic. To illustrate this, let’s create a simple component that displays a greeting message based on user input.

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

@Component({
  selector: 'app-greeting',
  template: `

Hello, {{name}}!

` }) export class GreetingComponent { name: string = ''; }

This component has a property name that is displayed in the template. Now, create a corresponding test file named greeting.component.spec.ts:

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

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

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [GreetingComponent]
    });
    fixture = TestBed.createComponent(GreetingComponent);
    component = fixture.componentInstance;
  });

  it('should display greeting message', () => {
    component.name = 'John';
    fixture.detectChanges();
    const compiled = fixture.nativeElement;
    expect(compiled.querySelector('p').textContent).toContain('Hello, John!');
  });
});

This test suite sets up the GreetingComponent for testing. The beforeEach function initializes the testing module and creates a component fixture. The it function checks whether the greeting message is displayed correctly when the name property is set to 'John'. The detectChanges method triggers Angular’s change detection, updating the view.

Component Interaction Testing

Testing interactions between components is crucial for ensuring the integrity of your application. Let’s create a parent component that contains the GreetingComponent and a button to update the name.

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

@Component({
  selector: 'app-parent',
  template: `
    
    
  `
})
export class ParentComponent {
  updateName() {
    // Logic to update name
  }
}

In the parent component, the updateName method is intended to change the name in the child component. The corresponding test for this interaction would check whether the button click updates the name accordingly.

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ParentComponent } from './parent.component';
import { GreetingComponent } from './greeting.component';

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

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [ParentComponent, GreetingComponent]
    });
    fixture = TestBed.createComponent(ParentComponent);
    component = fixture.componentInstance;
  });

  it('should change name in GreetingComponent when button is clicked', () => {
    const greetingComponent = fixture.debugElement.children[0].componentInstance;
    component.updateName();
    fixture.detectChanges();
    expect(greetingComponent.name).toBe('New Name');
  });
});

This test checks that the updateName method updates the name property in the GreetingComponent when the button is clicked.

Edge Cases & Gotchas

Testing in Angular can lead to some common pitfalls if not handled properly. One common issue is not cleaning up after tests, which can lead to state leakage between tests. Always use the afterEach function to reset any changes made during the tests:

afterEach(() => {
  // Reset any global state or clear mocks
});

Another gotcha is failing to handle asynchronous operations correctly. When testing async operations, use Jasmine’s done callback or return a promise to ensure that tests wait for completion:

it('should fetch data', (done) => {
  service.fetchData().then(data => {
    expect(data).toBeTruthy();
    done();
  });
});

Performance & Best Practices

To ensure optimal performance in your unit tests, follow these best practices:

  • Isolate tests: Each test should be independent to prevent one test’s failure from affecting others.
  • Mock dependencies: Use mocking for services and components that are not under test to reduce complexity and execution time.
  • Keep tests focused: Each test should cover a single logical scenario to improve readability and maintainability.
  • Run tests frequently: Integrate running tests into your CI/CD pipeline to catch issues early.

Real-World Scenario: Building a Simple Todo App

Let’s tie everything together in a simple Todo application that allows users to add and display tasks. The structure will include a TodoService for managing tasks and a TodoComponent for user interaction.

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

@Injectable({
  providedIn: 'root'
})
export class TodoService {
  private tasks: string[] = [];

  addTask(task: string) {
    this.tasks.push(task);
  }

  getTasks(): string[] {
    return this.tasks;
  }
}

This service manages a list of tasks, allowing tasks to be added and retrieved. Next, create the component:

import { Component } from '@angular/core';
import { TodoService } from './todo.service';

@Component({
  selector: 'app-todo',
  template: `
    
    
    
  • {{task}}
` }) export class TodoComponent { newTask: string = ''; tasks: string[] = []; constructor(private todoService: TodoService) {} addTask() { this.todoService.addTask(this.newTask); this.tasks = this.todoService.getTasks(); this.newTask = ''; } }

This component allows users to add tasks and displays them in a list. Now, write tests for the service and component to ensure they function correctly:

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

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

  it('should add and retrieve tasks', () => {
    service.addTask('Task 1');
    expect(service.getTasks()).toEqual(['Task 1']);
  });
});

This test checks that the TodoService can add and retrieve tasks accurately.

Component Tests

describe('TodoComponent', () => {
  let component: TodoComponent;
  let fixture: ComponentFixture;
  let todoService: TodoService;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [TodoComponent],
      providers: [TodoService]
    });
    fixture = TestBed.createComponent(TodoComponent);
    component = fixture.componentInstance;
    todoService = TestBed.inject(TodoService);
  });

  it('should add a task', () => {
    component.newTask = 'Task 1';
    component.addTask();
    expect(component.tasks).toContain('Task 1');
  });
});

This test verifies that tasks can be added through the component. By running these tests, you ensure that the Todo application behaves as expected.

Conclusion

  • Unit testing is essential for maintaining high code quality in Angular applications.
  • Jasmine provides a clean syntax for writing tests, while Karma runs them across different browsers.
  • Always mock dependencies and isolate tests to avoid side effects.
  • Integrate testing into your development workflow for better productivity and fewer bugs.
  • Real-world applications benefit significantly from robust unit testing practices.

S
Shubham Saini
Programming author at Code2Night — sharing tutorials on ASP.NET, C#, and more.
View all posts →

Related Articles

Mastering State Management in Angular with NgRx: A Comprehensive Guide
Mar 25, 2026
Mastering HTTP Interceptors in Angular for Enhanced API Communication
Mar 25, 2026
Mastering Route Guards in Angular: Understanding CanActivate and CanDeactivate
Mar 25, 2026
Mastering Angular Services and Dependency Injection for Scalable Applications
Mar 25, 2026
Previous in Angular
Mastering State Management in Angular with NgRx: A Comprehensive …

Comments

Contents

More in Angular

  • Tag or mention people like WhatsApp & Skype by using @ in An… 10384 views
  • How to Apply css on child components in Angular 10174 views
  • Export to Excel in Angular using ExcelJS? 9753 views
  • Angular Material Select Dropdown with Image 8266 views
  • How To Consume Web API Using Angular 4012 views
View all Angular posts →

Tags

AspNet C# programming AspNet MVC c programming AspNet Core C software development tutorial MVC memory management Paypal coding coding best practices data structures programming tutorial tutorials object oriented programming Slick Slider StripeNet
Free Download for Youtube Subscribers!

First click on Subscribe Now and then subscribe the channel and come back here.
Then Click on "Verify and Download" button for download link

Subscribe Now | 1760
Download
Support Us....!

Please Subscribe to support us

Thank you for Downloading....!

Please Subscribe to support us

Continue with Downloading
Be a Member
Join Us On Whatsapp
Code2Night

A community platform for sharing programming knowledge, tutorials, and blogs. Learn, write, and grow with developers worldwide.

Panipat, Haryana, India
info@code2night.com
Quick Links
  • Home
  • Blog Archive
  • Tutorials
  • About Us
  • Contact
  • Privacy Policy
  • Terms & Conditions
  • Guest Posts
  • SEO Analyzer
Free Dev Tools
  • JSON Beautifier
  • HTML Beautifier
  • CSS Beautifier
  • JS Beautifier
  • Password Generator
  • QR Code Generator
  • Hash Generator
  • Diff Checker
  • Base64 Encode/Decode
  • Word Counter
  • SEO Analyzer
By Language
  • Angular
  • Angular js
  • Asp.net Core
  • C
  • C#
  • DotNet
  • HTML/CSS
  • Java
  • JavaScript
  • Node.js
  • Python
  • React
  • Security
  • SQL Server
  • TypeScript
© 2026 Code2Night. All Rights Reserved.
Made with for developers  |  Privacy  ·  Terms
Translate Page
We use cookies to improve your experience and analyze site traffic. By clicking Accept, you consent to our use of cookies. Privacy Policy
Accessibility
Text size
High contrast
Grayscale
Dyslexia font
Highlight links
Pause animations
Large cursor