jest-plugin-must-assert
A plugin extending the default Jest behavior to fail any tests which do not
perform a runtime assertion.
Problem
Asynchronous tests could be challenging to get right, particularly for junior
developers or engineers new to async JavaScript. The most common mistake is an async
test which does not fire any assertions, either due to logic or even syntax errors.
Static analysis (linters) gets close to pointing out the issues, but is not enough to catch logic mistakes.
For this, we require a runtime check that some assertion was run during the test.
Jest, unfortunately, has no "failWithoutAssertions" configuration options, so this plugin aims to remedy that.
The plugin patches the Jest API to force tests without any assertions to fail. In addition
to failing tests without assertions this plugin also patches a bug in Jest which
leads to assertions "leaking" accross different tests.
Install
npm i -D jest-plugin-must-assert
or
yarn add -D jest-plugin-must-assert
For default behavior, add the plugin to your setup files.
Supported Jest Environments
jest-plugin-must-assert
- Default supported environment, node
jest-plugin-must-assert/jsdom
- JSDOM environment support. Necessary for
mocking window task functions like setTimeout
when using jest-environment-jsdom
.
Useful for React tests.
Use
For a specific test file
You may import the plugin into any test file you need additional safeguard for async logic.
import 'jest-plugin-must-assert';
test('some logic', () => {
setTimeout(() => expect(1).toBe(2));
...
});
For entire test suite
Alternatively, you can enable the plugin for an entire test suite by adding it
to your jest configuration.
...
setupFilesAfterEnv: ['jest-plugin-must-assert'],
...
Manual configuration
You may also extend the default behavior with the following, manual configuration.
const patchJestAPI = require('jest-plugin-must-assert/manual');
patchJestAPI({
onInvokeTask({
originZoneId,
currentZoneId,
testName,
task,
}) {
if (originZoneId !== currentZoneId) {
throw new Error(
`Test "${testName}" is attempting to invoke a ${task.type}(${task.source}) after test completion. Ignoring`
);
}
return true;
},
logger,
ignoreStack = [/Zone/, /zone\.js/, /node_modules/],
});
Then in your config file:
...
setupFilesAfterEnv: [
'<rootDir>/must-assert-setup'
],
...
Performance
There are some performance implications of using this plugin as it does add a bit of
overhead, but from testing it's a trivial increase. This plugin has been tested
within a project with 1600+ test suites and over 10k individual tests, with only a negligible slow-down.