Skip to content

Getting started

@mnaoumov/typescript-test-toolkit is generic test support for TypeScript projects: a per-test setup for Vitest, Jest or any other framework, async-operation tracking, strictProxy and mock helpers. It depends on @mnaoumov/typescript-lib only.

Install it as a dev dependency:

Terminal window
npm install --save-dev @mnaoumov/typescript-test-toolkit

vitest and @jest/globals are optional peer dependencies: install whichever framework the project runs.

Point the test runner at the setup file for its framework, and every test starts from isolated state:

vitest.config.ts
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
setupFiles: ['@mnaoumov/typescript-test-toolkit/vitest-setup']
}
});

Testing describes what the setup does before and after each test, and how to wire it into Jest or another framework.

Every module is a subpath of the package, named after its file:

import { waitForAllAsyncOperations } from '@mnaoumov/typescript-test-toolkit/async-operation-tracking';
import { mockImplementation } from '@mnaoumov/typescript-test-toolkit/mock-implementation';
import { strictProxy } from '@mnaoumov/typescript-test-toolkit/strict-proxy';

strictProxy turns a partial object into a mock of the full type that throws on every member the partial did not provide, so a test that reaches an unmocked member fails at that line instead of carrying undefined onward:

import { strictProxy } from '@mnaoumov/typescript-test-toolkit/strict-proxy';
interface FileStore {
readFile(path: string): Promise<string>;
writeFile(path: string, content: string): Promise<void>;
}
const fileStore = strictProxy<FileStore>({
readFile: async () => 'content'
});
await fileStore.readFile('a.txt');
await fileStore.writeFile('a.txt', ''); // Throws: Unmocked property "writeFile" was accessed on mock object

Nested plain objects are wrapped too. Properties that test tooling probes while printing a value, such as then, toJSON and Symbol.iterator, pass through rather than throw. bypassStrictProxy returns the object underneath, for reading an optional member without tripping the proxy.

mockImplementation (Vitest only) spies on a method and hands the replacement the original implementation as its first argument, so a test can wrap the real behavior rather than replace it:

import { mockImplementation } from '@mnaoumov/typescript-test-toolkit/mock-implementation';
const spy = mockImplementation({
$object: service,
impl(originalImplementation, path) {
return path === 'missing.txt' ? null : originalImplementation.call(this, path);
},
method: 'load'
});

Spying on the same method twice still passes the true original, not the first spy.

  • Testing: the per-test setup, async-operation tracking and the failures it raises.
  • API reference: every module and export, generated from the package’s TSDoc.