Migrating From Jest to Vitest
💾 Use Both Jest & Vitest
In the rare occurrence where some tests are too coupled to Jest and hard to automatically migrate to Vitest, you can keep the Jest's configuration files and run some specific tests with Jest and others with Vitest. This will help you migrate progressively. Otherwise, you can simply remove the Jest setup.
1. Backup Jest's test-setup.ts
file (or remove it)
git mv {MY_PROJECT}/src/test-setup.ts {MY_PROJECT}/src/test-setup.jest.ts
2. Update jest.config.ts
(or remove it)
Update the jest.config.ts
configuration to use the test-setup.jest.ts
file and match test files ending with .jest.spec.ts
.
- setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
+ setupFilesAfterEnv: ['<rootDir>/src/test-setup.jest.ts'],
+ testRegex: '(/__tests__/.*|(\\.|/)jest\.(test|spec))\\.[jt]sx?$',
3. Rename test
Target
Rename the test
target to jest
in project.json
(if you are using Nx) or angular.json
(if you are using Angular CLI).
"architect|targets": {
- "test": {
+ "jest": {
"builder": "...",
...
}
...
}
You will be able to run the Jest tests with the following command:
nx jest {MY_PROJECT}
# or
ng run {MY_PROJECT}:jest
🗑️ or Remove Jest
Remove Jest configuration files:
rm -f {MY_PROJECT}/jest.config.ts {MY_PROJECT}/src/test-setup.ts
Remove the test
target from project.json
(if you are using Nx) or angular.json
(if you are using Angular CLI).
"architect|targets": {
- "test": {...}
...
}
📦 Set Up Vitest
For Nx Users
If you are using Nx (>= 20.3.0), you can run the following commands to set up Vitest in your Angular project:
nx add @nx/vite
nx g vitest --project {MY_PROJECT}
For Angular CLI Users
If you are using the Angular CLI, you can use Analog's generator to set up Vitest in your Angular project.
ng g @analogjs/platform:setup-vitest --project {MY_PROJECT}
Note that this does not set up anything specific to Analog. It is just a convenient way to set up Vitest in your Angular project.
The Analog team did an outstanding job of making it easy to use Vitest with Angular projects.
Update src/test-setup.ts
You may need to update the src/test-setup.ts
file to apply whatever previous setup you had in Jest to Vitest.
🧳 Migrate Tests
Vitest shares a large API surface with Jest, so most of the tests should work without any changes.
However, if your tests are using Jest-specific APIs (e.g. jest.fn()
), you may need to update them.
In general, I'd recommend staying as decoupled as possible from the testing framework. For instance, it is better to use fakes than mocks or spies. Cf. 📺 Fake it till you Mock it.
🤖 Automatic Migration
There is a Jest to Vitest codemod that will automatically transform most Jest-specific API usages to their Vitest equivalent.
You can run it with the following command:
npx codemod jest/vitest -t path/to/the/test/files/you/want/to/migrate
The codemod will make transforms such as:
- test(...);
+ import { test } from 'vitest';
+ test(...);
- jest.mock(...);
+ import { vi } from 'vitest';
+ vi.mock(...);
- jest.fn();
+ import { vi } from 'vitest';
+ vi.fn();
It is not exhaustive but should cover most of the common cases and help you migrate faster.
👷 Manual Migrations
Replace done
callback with a Promise
Vitest does not support the done
callback. A quick way to migrate this is to wrap the test body in a Promise
like this.
- it('should do something', (done) => {
- // ...
- done();
- });
+ it('should do something', () => new Promise((done) => {
+ // ...
+ done();
+ }));
Ideally, the done
callback pattern should be avoided.
Prefer converting any async code to promises:
import { lastValueFrom } from 'rxjs';
test('...', async () => {
const source$: Observable<...> = ...;
const result = await lastValueFrom(source$);
expext(result).toEqual(...);
})
I'll elaborate on other techniques in a future chapter.
🚀 Run Tests
You can run the tests with the following command:
nx test {MY_PROJECT}
# or
ng test {MY_PROJECT}
🙋 F.A.Q.
Nx creates a project with Jest by default. How can I change it to use Vitest?
This happens when the default unitTestRunner
option is set to jest
in the nx.json
file. You can change it to vitest
:
"generators": {
"@nx/angular:application": {
...
- "unitTestRunner": "jest"
+ "unitTestRunner": "vitest"
}
}
I can't see vitest
in the list of suggested test runners
The vitest
option for Angular projects is available in Nx 20.1.0 or later.
🙀 Common Errors & Issues
Error: Expected to be running in 'ProxyZone', but it was not found
This often happens with tests relying on Angular's fakeAsync
.
For fakeAsync
to work, Angular has to monkey patch the test
function to use zones. Analog's Vitest plugin already does this for you.
This is actually what is happening under the hood in the @analogjs/vitest-angular/setup-zone
module imported in the test-setup.ts
file.
This behavior is broken when we import beforeEach
, test
, it
, and others from vitest
instead of using the global ones that are monkey patched.
To fix this, you will have to remove the import and make sure to use the global functions.
- import { describe, it } from 'vitest';
describe('...', () => {
it('...', () => {
// ...
});
});
It is better to avoid using fakeAsync
and prefer using Vitest's fake timers instead.
Error: Cannot set base providers because it has already been called
Replace:
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting(),
);
with:
beforeEach(() => {
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting(),
);
});
afterEach(() => {
getTestBed().resetTestEnvironment();
});