How to migrate from Jest to node:test
Jest is one of the most populars testing frameworks for Javascript and Node.js. Originally developed by Facebook, it’s a one-stop-shop with testing, assertions, code coverage… but this implies some critics, like requiring more than 50mb of dependencies. Also, somewhat recently was shown to be maintained mostly by a single person, being that the reason why updates and maintenance was so much slow, so they decided to transfer it to OpenJS foundation. Also there has been several long standing critics about not providing a pure environment, or the fact that Jest parses the code, leading to some complexities when needing to configure transpilation. That has lead to several people looking for alternatives, and having now a built-in test runner in Node.js, I decided to see myself how to migrate to it.
First of all, it’s to identify the replacements for the different Jest features. As already shown, node:test module can the used as the test runner and for mocking, meanwhile assert module can mostly be used for assertions. A tough topic are inline snapshots, since it’s a feature I use a lot. Luckily Jest snapshot engine is provided as an independent module, but it don’t have documentation at all and it’s very tightly coupled with Jest itself. There are some modules that wrap it and add support for chai like chai-jest-snapshot and mocha-chai-jest-snapshot, so it can works as a solution, but not only that would add an extra assertions library, but also there’s no support for inline snapshots, just only regular ones. I tried to create my own wrapper without making use of any extra dependency and adding the support for inline snapshots, but lack of documentation makes it difficult. Maybe I’ll try again in the future (anybody interested on sponsors me? :-) ).
Having now the elements, doing the migration is surprisingly pretty straighforward:
- Add
chai
andchai-jest-snapshot
as dev dependencies, and remove any Jest related dependency and configuration. - Rename
__tests__
folder(s) totest
. - Replace
jest
command withnode --test
. -
Add the
node:test
functions that previously were set as globals by Jest:import { afterEach, before, beforeEach, describe, mock, test, throws } from 'node:test'
-
Enable the snapshot support, and the replacement of the
expect()
function:import chai, {expect} from 'chai' import chaiJestSnapshot from 'chai-jest-snapshot' chai.use(chaiJestSnapshot) before(function() { chaiJestSnapshot.resetSnapshotRegistry() })
Since
node:test
run each test in a different process, we need to add the snapshot support in each test file. - Comment or remove calls to
expect.assertions()
, since there’s no equivalent innode:test
. This was possible on Jest since assertions were integrated in the tests runner. - Await the
Promise
s instead ofexpect()
on them (expect(await promise)
instead ofawait expect(promise).resolves
). - Replace Jest idioms:
-
expect(func).toThrowErrorMatchingInlineSnapshot(error)
withthrows(func, error)
-
expect(value).toBe(expected)
withdeepStrictEqual(value, expected)
-
expect(value).toBeInstanceOf(class)
withok(value instanceof class)
-
expect(value).toBeUndefined()
withifError(value)
-
expect(value).toMatchSnapshot()
withexpect(value).to.matchSnapshot()
-
Missing points as already commented, would be the support for inline snapshots, and maybe create a codemods to automate the process :-)
Previously published at https://piranna.github.io/2023/04/24/How-to-migrate-from-Jest-to-node-test/