jest
debug jest on windows
plaintextnode --inspect-brk ./node_modules/jest/bin/jest.js --runInBand
then click Inspect on the target in chrome://inspect
extending stacktrace length
Jest cutting off stack traces too early when tests fail? Make them longer with:
plaintextError.stackTraceLimit = 50;
find skipped tests
shellnpm i -D jest-skipped-reporter npm run test -- --reporters jest-skipped-reporter
mocking an internally called function
Problem
Mocking a function that is called within the same module and asserting on the caller does not work - the original function will be called and not the mock.
myModule.ts
typescriptexport const myFunction = () => { return "not mocked"; }; export const myCallingFunction = () => { return myFunction(); };
myModule.test.ts
typescriptimport * as myModule from "./myModule"; beforeEach(() => { jest.spyOn(myModule, "myFunction").mockReturnValue("mocked"); }); it("should mock", () => { const result = myModule.myFunction(); expect(result).toBe("mocked"); }); it("should mock caller", () => { const result = myModule.myCallingFunction(); expect(result).toBe("mocked"); });
Fails with:
plaintextFAIL src/myModule.test.ts ✓ should mock (3 ms) ✕ should mock caller (3 ms) ● should mock caller expect(received).toBe(expected) // Object.is equality Expected: "mocked" Received: "not mocked" 11 | it("should mock caller", () => { 12 | const result = myModule.myCallingFunction(); > 13 | expect(result).toBe("mocked"); | ^ 14 | }); 15 | at Object.<anonymous> (src/machines/myModule.test.ts:13:18) Test Suites: 1 failed, 1 total Tests: 1 failed, 1 passed, 2 total
Solution
To fix, import the module into itself and reference the import in the caller:
myModule.ts - fixed
typescriptimport * as self from "./myModule"; export const myFunction = () => { return "not mocked"; }; export const myCallingFunction = () => { return self.myFunction(); };
Passes:
plaintextPASS src/myModule.test.ts ✓ should mock (3 ms) ✓ should mock caller (1 ms) Test Suites: 1 passed, 1 total Tests: 2 passed, 2 total
Other options include switching to class or splitting into separate files.
See facebook/jest#936, specifically the summary, and then using a self reference
force luxon to a specific time in utc
Mock luxon’s time to be 2021-02-25 UTC:
javascriptSettings.now = () => new Date(Date.UTC(2021, 1, 25, 0, 0, 0)).valueOf();
mocking functions with spyOn
myModule.js
jsexport const myFunction = () => "hello";
myModule.test.js
jsimport * as myModule from "./myModule"; jest.spyOn(myModule, "myFunction").mockImplementation(() => "goodbye");
mocking a dependency function imported by a module under test
If we have a module:
someModule.js
javascriptexport const someFunction = () => { console.log("does something"); };
which is a dependency of another module under test:
moduleUnderTest.js
javascriptimport { someFunction } from "./someModule"; export const underTest = () => { // ... someFunction(); // ... };
then, in our test, we can mock and inspect the dependency:
moduleUnderTest.test.js
javascriptimport { underTest } from "./moduleUnderTest"; import { someFunction } from "./someModule"; // this bit was weird jest.mock("./someModule"); describe("underTest", () => { it("called someFunction", () => { underTest(); expect(someFunction).toHaveBeenCalled(); }); });
mocking react-router
Use hooks and mock them instead;
javascriptjest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useParams: () => ({ myRoute: 'some-route-value', }), }));
using typescript with jest
Run in shell:
bashnpm i --save-dev jest \ @types/jest \ babel-jest \ @babel/core \ @babel/preset-env \ @babel/preset-typescript
Save to babel.config.js:
jsmodule.exports = { presets: [ ["@babel/preset-env", { targets: { node: "current" } }], "@babel/preset-typescript", ], };
links
Mark tests that test overall behaviour other tests expand on in more detail proposes improving Jest’s test output by allowing tests to be marked as dependent on others, helping focus on root causes when failures occur in test suites with overlapping assertions. Utlimately this was closed as not planned and --bail was suggested as an alternative.