Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setup global providers for Angular unit tests

I have generated a fresh Angular 18 project and made it zoneless. It works fine, however in all of my unit tests I am now getting the following error:

Error: NG0908: In this configuration Angular requires Zone.js

I resolved the error by adding provideZonelessChangeDetection() to each TestBed's providers, however it's quite annoying needing to add this manually to every spec file. Also it pops up again every time I generate a new component.

Is there a way to set up this provider globally for all unit tests? I have read that in the src/test.ts file it is possible to globally configure the tests, but in my project this file does not exist.

like image 271
JSON Derulo Avatar asked Jun 21 '26 14:06

JSON Derulo


1 Answers

There are two approaches to solve this issue:

  1. Migrate to the unit-test builder and add a providersFile
  2. Setup a test.ts file

1. Setup a providersFile in the unit-test builder

In Angular v20, experimental support for a new unit testing system was added. In v21 it was advanced to stable and is now the default for newly generated projects. The main goal of this system is to provide support for other unit test runners such as vitest. But it also has a feature that helps setting up global providers.

Create a new file src/test-providers.ts and export an array with the providers that you want to have in all unit tests:

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

export default [provideZonelessChangeDetection()];

Now update your angular.json and set the providersFile option of the unit-test runner:

{
  "projects": {
    "your-project": {
      "architect": {
        "test": {
          "builder": "@angular/build:unit-test",
          "options": {
            "buildTarget": "::development",
            "runner": "vitest",
            "providersFile": "src/test-providers.ts",
            "tsConfig": "tsconfig.spec.json"
          }
        }
      }
    }
  }
}

Finally, make sure that the file is included in the files array of the tsconfig.spec.json:

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "./out-tsc/spec",
    "types": ["@angular/localize"]
  },
  "files": ["src/test-providers.ts"],
  "include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
}

2. Setup a test.ts file

Older Angular projects used to have a test.ts file where the modules for all tests can be configured. Apparently in newer Angular projects, this file is not automatically generated anymore. However, it can be created manually.

The next challenge is that initTestEnvironment() only accepts modules, no providers. To solve this issue, I created a module with a provider:

import { NgModule, provideZonelessChangeDetection } from '@angular/core';
import { getTestBed } from '@angular/core/testing';
import {
  BrowserTestingModule,
  platformBrowserTesting,
} from '@angular/platform-browser/testing';

@NgModule({
  // pre Angular v20, use provideExperimentalZonelessChangeDetection
  providers: [provideZonelessChangeDetection()],
})
class ZonelessModule {}

getTestBed().initTestEnvironment(
  [BrowserTestingModule, ZonelessModule],
  platformBrowserTesting(),
);

Now this file needs to be registered in the angular.json via the main option:

{
  "projects": {
    "my-project": {
      "architect": {
        // ...
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "src/test.ts",
            "tsConfig": "tsconfig.spec.json",
            "inlineStyleLanguage": "scss",
            "assets": [
              {
                "glob": "**/*",
                "input": "public"
              }
            ],
            "styles": ["src/styles.scss"],
            "scripts": [],
            "polyfills": ["@angular/localize/init"]
          }
        }
      }
    }
  }
}

Finally, the file needs to be added to to the files of the tsconfig.spec.json:

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "./out-tsc/spec",
    "types": ["jasmine", "@angular/localize"]
  },
  "files": ["src/test.ts"],
  "include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
}
like image 176
JSON Derulo Avatar answered Jun 23 '26 05:06

JSON Derulo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!