{"id":16222144,"url":"https://github.com/hugodf/mock-spy-module-import","last_synced_at":"2025-03-19T11:31:19.437Z","repository":{"id":36435335,"uuid":"196837971","full_name":"HugoDF/mock-spy-module-import","owner":"HugoDF","description":"JavaScript import/require module testing do's and don'ts with Jest","archived":false,"fork":false,"pushed_at":"2023-03-04T04:20:37.000Z","size":1144,"stargazers_count":57,"open_issues_count":4,"forks_count":12,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-02-28T18:33:58.110Z","etag":null,"topics":["commonjs","esm","internals","javascript","jest","jest-mocking","lint","mocking","monorepo","spy","stub","yarn","yarn-workspaces"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/HugoDF.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-07-14T13:10:18.000Z","updated_at":"2024-04-19T00:05:36.000Z","dependencies_parsed_at":"2024-10-10T12:11:29.835Z","dependency_job_id":"ba1eed0d-3389-42b7-aacd-f671a9528388","html_url":"https://github.com/HugoDF/mock-spy-module-import","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HugoDF%2Fmock-spy-module-import","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HugoDF%2Fmock-spy-module-import/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HugoDF%2Fmock-spy-module-import/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HugoDF%2Fmock-spy-module-import/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/HugoDF","download_url":"https://codeload.github.com/HugoDF/mock-spy-module-import/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243989109,"owners_count":20379648,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["commonjs","esm","internals","javascript","jest","jest-mocking","lint","mocking","monorepo","spy","stub","yarn","yarn-workspaces"],"created_at":"2024-10-10T12:11:25.126Z","updated_at":"2025-03-19T11:31:19.068Z","avatar_url":"https://github.com/HugoDF.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mock/Spy module imports or internals with Jest\n\nJavaScript import/require module testing do's and don'ts with Jest\n\n## Requirements\n\n- Node 10\n- Yarn 1.x\n\n## Setup\n\n1. Clone the repository\n2. Run `yarn`: installs all required dependencies.\n4. Run `yarn test` to run all the tests.\n\n## npm scripts\n\n- `yarn test` will run each example's test suites.\n- `yarn lint` will lint all of the example files (and tests)\n- `yarn format` will run lint with `--fix` option on all the examples files (and tests).\n\n## Guide\n\n### Types of imports\n\nModern JavaScript has 2 types of imports:\n\n- CommonJS: Node.js' built-in import system which uses calls to a global `require('module-y')` function, packages on npm expose a CommonJS compatible entry file.\n- ES Modules (ESM): modules as defined by the ECMAScript standard. It uses `import x from 'module-y'` syntax.\n\nThere are also (legacy) module loaders like RequireJS and AMD but CommonJS and ESM are the current and future most widespread module definition formats for JavaScript.\n\nES Modules have 2 types of exports: named exports and default exports.\n\nA named export looks likes this: `export function myFunc() {}` or `export const a = 1`.\n\nA default export looks like this: `export default somethingAlreadyDefined`.\n\nA named export can be imported by itself using syntax that looks (and works) a bit like object destructuring: `import { myFunc, a } from './some-module'`.\n\nIt can also be imported as a namespace: `import * as moduleY from './module-y'` (can now use `moduleY.myFunc()` and `moduleY.a`).\n\nA default export can only be imported with a default import: `import whateverIsDefault from './moduleY'`.\n\nTheses 2 types of imports can also be mixed and matched, [see `import` docs on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import).\n\n### Intercepting imports\n\nWhen unit-testing, you may want to stub/mock out module(s) that have their own battery of unit tests.\n\nIn Jest, this is done with `jest.mock('./path/of/module/to/mock', () =\u003e ({ /* fake module */ }))`.\n\nIn this case the CommonJS and ES6 Module mocks look quite similar. There are a few general gotchas.\n\nFirst off, what you're mocking with (2nd parameter of `jest.mock`) is a factory for the module. ie. it's a function that returns a mock module object.\n\nSecond, if you want to reference a variable from the parent scope of `jest.mock` (you want to define your mock module instance for example), you need to prefix the variable name with `mock`.\nFor example:\n\n```js\nconst mockDb = {\n  get: jest.fn(),\n  set: jest.fn()\n};\nconst db = mockDb\n\n// This works\njest.mock('./db', () =\u003e mockDb);\n\n// This doesn't work\njest.mock('./db', () =\u003e db);\n```\n\nFinally, you should call `jest.mock` _before_ importing the module under test (which itself imports the module we just mocked).\n\nIn practice, Babel ESM -\u003e CommonJS transpilation hoists the `jest.mock` call so it's usually not an issue 🤷‍♀.\n\n#### The CommonJS case\n\nThe full test and code under test is at [examples/intercept-imports-cjs](./examples/intercept-imports-cjs).\n\nThe relevant snippets are the following:\n```js\njest.mock('./db', () =\u003e ({\n  get: jest.fn(),\n  set: jest.fn()\n}));\n\nconst mockDb = require('./db');\nconst {addTodo, getTodo} = require('./lib');\n\ntest('CommonJS \u003e addTodo \u003e inserts with new id', async () =\u003e {\n  await addTodo({name: 'new todo'});\n  expect(mockDb.set).toHaveBeenCalledWith('todos:1', {name: 'new todo', id: 1});\n});\n\ntest('CommonJS \u003e getTodo \u003e returns output of db.get', async () =\u003e {\n  mockDb.get.mockResolvedValueOnce({\n    id: 1,\n    name: 'todo-1'\n  });\n\n  const expected = {\n    id: 1,\n    name: 'todo-1'\n  };\n  const actual = await getTodo(1);\n\n  expect(mockDb.get).toHaveBeenCalledWith('todos:1');\n  expect(actual).toEqual(expected);\n});\n```\n\n#### ES Modules default export\n\nThe full test and code under test is at [examples/intercept-imports-esm-default](./examples/intercept-imports-esm-default).\n\n```js\nimport mockDb from './db';\n\nimport lib from './lib';\n\njest.mock('./db', () =\u003e ({\n  get: jest.fn(),\n  set: jest.fn()\n}));\n\nconst {addTodo, getTodo} = lib;\n\ntest('ESM Default Export \u003e addTodo \u003e inserts with new id', async () =\u003e {\n  await addTodo({name: 'new todo'});\n  expect(mockDb.set).toHaveBeenCalledWith('todos:1', {name: 'new todo', id: 1});\n});\n\ntest('ESM Default Export \u003e getTodo \u003e returns output of db.get', async () =\u003e {\n  mockDb.get.mockResolvedValueOnce({\n    id: 1,\n    name: 'todo-1'\n  });\n\n  const expected = {\n    id: 1,\n    name: 'todo-1'\n  };\n  const actual = await getTodo(1);\n\n  expect(mockDb.get).toHaveBeenCalledWith('todos:1');\n  expect(actual).toEqual(expected);\n});\n```\n\n#### ES Modules named export\n\nThe full test and code under test is at [examples/intercept-imports-esm-named](./examples/intercept-imports-esm-named).\n\n```js\nimport * as mockDb from './db';\n\nimport {addTodo, getTodo} from './lib';\n\njest.mock('./db', () =\u003e ({\n  get: jest.fn(),\n  set: jest.fn()\n}));\n\ntest('ESM named export \u003e addTodo \u003e inserts with new id', async () =\u003e {\n  await addTodo({name: 'new todo'});\n  expect(mockDb.set).toHaveBeenCalledWith('todos:1', {name: 'new todo', id: 1});\n});\n\ntest('ESM named export \u003e getTodo \u003e returns output of db.get', async () =\u003e {\n  mockDb.get.mockResolvedValueOnce({\n    id: 1,\n    name: 'todo-1'\n  });\n\n  const expected = {\n    id: 1,\n    name: 'todo-1'\n  };\n  const actual = await getTodo(1);\n\n  expect(mockDb.get).toHaveBeenCalledWith('todos:1');\n  expect(actual).toEqual(expected);\n});\n```\n\n### Spying/Stubbing calls to internal module functions\n\n\u003e Warning: you should not be spying/stubbing module internals, that's your test reaching into the implementation, which means test and code under test are tightly coupled\n\nConcept: \"calling through\" (as opposed to mocking).\n\nAn internal/private/helper function that isn't exported should be tested through its public interface, ie. not by calling it, since it's not exported, but by calling the function that calls it.\n\nTesting its functionality is the responsibility of the tests of the function(s) that consume said helper.\n\nThis is for the cases where:\n\n- you don't have the time to extract the function but the complexity is too high to test through (from the function under test into the internal function)\n  - solution: you should probably _make_ time\n- the internal function belongs in said module but its complexity make it unwieldy to test through.\n  - solution: you should probably extract it\n- the function is not strictly internal, it's exported and unit tested, thereforce calling through would duplicate the tests.\n  - solution: you should definitely extract it\n\nIn the following cases we'll be looking to stub/mock/spy the internal `makeKey` function. This is purely for academic purposes since, we've shown in the section above how to **test through** the `getTodo` call.\n\nIn that situation we were testing `expect(mockDb.get).toHaveBeenCalledWith('todos:1');` (see [examples/intercept-imports-cjs/lib.jest-test.js](./examples/intercept-imports-cjs/lib.jest-test.js)). The generation of the `todos:1` key is the functionality of `makeKey`, that's an example of testing by **calling through**.\n\n#### CommonJS\n\n##### A module where internal functions can't be mocked\n\nCode listing lifted from [examples/spy-internal-calls-cjs/lib.fail.js](./examples/spy-internal-calls-cjs/lib.fail.js).\n\n```js\nconst db = require('./db');\n\nconst keyPrefix = 'todos';\nconst makeKey = key =\u003e `${keyPrefix}:${key}`;\n\nfunction getTodo(id) {\n  return db.get(makeKey(id));\n}\n\nmodule.exports = {\n  makeKey,\n  getTodo\n};\n```\n\nAs you can see when you run the [examples/spy-internal-calls-cjs/lib.fail.jest-test.js](./examples/spy-internal-calls-cjs/lib.fail.jest-test.js) tests, there's no way to intercept calls to `makeKey`.\n\n##### A module where internal function _can_ be mocked\n\nCode listing lifted from [examples/spy-internal-calls-cjs/lib.js](./examples/spy-internal-calls-cjs/lib.js).\n\n```js\nconst db = require('./db');\n\nconst keyPrefix = 'todos';\nconst makeKey = key =\u003e `${keyPrefix}:${key}`;\n\nconst lib = {\n  // Could also define makeKey inline like so:\n  // makeKey(key) { return `${keyPrefix}:${key}` },\n  makeKey,\n  getTodo(id) {\n    return db.get(lib.makeKey(id));\n  }\n};\n\nmodule.exports = lib;\n```\n\n##### Mocking/Spying the internal function\n\nCode listing lifted from [examples/spy-internal-calls-cjs/lib.jest-test.js](./examples/spy-internal-calls-cjs/lib.jest-test.js)\n\n```js\n// ignore setup code\ntest(\"CommonJS \u003e Mocking destructured makeKey doesn't work\", async () =\u003e {\n  const mockMakeKey = jest.fn(() =\u003e 'mock-key');\n  makeKey = mockMakeKey;\n  await getTodo(1);\n  expect(makeKey).not.toHaveBeenCalled();\n  expect(mockDb.get).not.toHaveBeenCalledWith('mock-key');\n});\n\ntest('CommonJS \u003e Mocking lib.makeKey works', async () =\u003e {\n  const mockMakeKey = jest.fn(() =\u003e 'mock-key');\n  lib.makeKey = mockMakeKey;\n  await getTodo(1);\n  expect(mockMakeKey).toHaveBeenCalledWith(1);\n  expect(mockDb.get).toHaveBeenCalledWith('mock-key');\n});\n\ntest('CommonJS \u003e Spying lib.makeKey works', async () =\u003e {\n  const makeKeySpy = jest\n    .spyOn(lib, 'makeKey')\n    .mockImplementationOnce(() =\u003e 'mock-key');\n  await getTodo(1);\n  expect(makeKeySpy).toHaveBeenCalled();\n  expect(mockDb.get).toHaveBeenCalledWith('mock-key');\n});\n```\n\nFrom the above we can see that with the setup from the previous section (see [examples/spy-internal-calls-cjs/lib.js](./examples/spy-internal-calls-cjs/lib.js)), we're able to both replace the implementation of `lib.makeKey` with a mock and spy on it.\n\nWe're still unable to replace our reference to it. That's because when we destructure `lib` to extract `makeKey` we create a copy of the reference ie. `makeKey = newValue` changes the implementation of the `makeKey` variable we have in our test file but doesn't replace the behaviour of `lib.makeKey` (which is what `getTodo` is calling).\n\nTo illustrate:\n```js\nconst lib = require('./lib');\nlet {makeKey} = lib;\n\nmakeKey = 'something';\n\n// `lib.makeKey` and `makeKey` are now different...\n```\n\n#### ES Modules\n\n##### Difficulty of Named exports\n\nIn the case of ES6 Modules, semantically, it's quite difficult to set the code up in a way that would work with named exports, the following code doesn't quite work:\n```js\nimport db from './db';\n\nconst keyPrefix = 'todos';\nexport const makeKey = key =\u003e `${keyPrefix}:${key}`;\n\nexport function getTodo(id) {\n  return db.get(makeKey(id));\n}\n```\nCode listing lifted from [examples/spy-internal-calls-esm/lib.named-export.js](./examples/spy-internal-calls-esm/lib.named-export.js), tests showing there's no simple way to mock/spy on `makeKey` are at [examples/spy-internal-calls-esm/lib.named-export.jest-test.js](./examples/spy-internal-calls-esm/lib.named-export.jest-test.js)\n\n##### Unmockeable modules with default exports\n\nCode listing lifted from [examples/spy-internal-calls-esm/lib.default-export.js](./examples/spy-internal-calls-esm/lib.default-export.js).\n\n```js\nimport db from './db';\n\nconst keyPrefix = 'todos';\nconst makeKey = key =\u003e `${keyPrefix}:${key}`;\n\nfunction getTodo(id) {\n  return db.get(makeKey(id));\n}\n\nconst lib = {\n  makeKey,\n  getTodo\n};\n\nexport default lib;\n```\n\nTests showing there's no simple way to mock/spy on `makeKey` are at [examples/spy-internal-calls-esm/lib.default-export.jest-test.js](./examples/spy-internal-calls-esm/lib.default-export.jest-test.js).\n\nThe reason this doesn't work is the same as the CommonJS example, `makeKey` is directly referenced and that reference can't be modified from outside of the module.\n\nAnything attempting import it would make a copy and therefore wouldn't modify the internal reference.\n\n##### Mock/Spy setup with ESM\n\nCode listing lifted from [examples/spy-internal-calls-esm/lib.js](./examples/spy-internal-calls-esm/lib.js)\n\n```js\nimport db from './db';\n\nconst keyPrefix = 'todos';\nconst makeKey = key =\u003e `${keyPrefix}:${key}`;\n\nconst lib = {\n  // Could also define makeKey inline like so:\n  // makeKey(key) { return `${keyPrefix}:${key}` },\n  makeKey,\n  getTodo(id) {\n    return db.get(lib.makeKey(id));\n  }\n};\n\nexport default lib;\n```\n\nPassing tests for the above are at [examples/spy-internal-calls-esm/lib.jest-test.js](./examples/spy-internal-calls-esm/lib.jest-test.js)\n\n**Note**, it would be possible to do something similar with named exports:\n\n```js\nimport db from './db';\n\nconst keyPrefix = 'todos';\nconst makeKey = key =\u003e `${keyPrefix}:${key}`;\n\nexport const lib = {\n  // Could also define makeKey inline like so:\n  // makeKey(key) { return `${keyPrefix}:${key}` },\n  makeKey,\n  getTodo(id) {\n    return db.get(lib.makeKey(id));\n  }\n};\n```\n\nThe key point is around exporting a `lib` object and referencing that same object when calling `makeKey`.\n\n#### Nothing to do with ESM/CommonJS\n\nBeing able to mock a part of a module is all about references.\n\nIf a function is calling another function using a reference that's not accessible from outside of the module (more specifically from our the test), then it can't be mocked.\n\n### Spy on imports or mock part of a module by \"referencing the module\"\n\n\u003e Warning: this will cause you to change the way you write your code just to accomodate a specific type of testing.\n\u003e\n\u003e This will break if anyone decides to get a copy of the module's function instead of calling `module.fn()` directly.\n\n#### CommonJS: Spy import/mock part of a module with Jest\n\nCode listing lifted from [examples/spy-module-cjs/lib.js](./examples/spy-module-cjs/lib.js).\n\nNote how the `db` module is imported without destructuring and how any calls to it are done using `db.method()` calls.\n\n```js\nconst db = require('./db');\n\nconst keyPrefix = 'todos';\nconst makeKey = key =\u003e `${keyPrefix}:${key}`;\n\nlet autoId = 1;\n\nasync function addTodo(todo) {\n  const id = autoId++;\n  const insertable = {\n    ...todo,\n    id\n  };\n  await db.set(makeKey(id), insertable);\n}\n\nfunction getTodo(id) {\n  return db.get(makeKey(id));\n}\n\nmodule.exports = {\n  addTodo,\n  getTodo\n};\n```\n\nWe are now able to spy on `db.method` using the following approach:\n\n```js\nconst db = require('./db');\n\nconst {addTodo, getTodo} = require('./lib');\n\nbeforeEach(() =\u003e jest.clearAllMocks());\n\ntest('CommonJS \u003e addTodo \u003e inserts with new id', async () =\u003e {\n  const dbSetSpy = jest.spyOn(db, 'set').mockImplementation(() =\u003e {});\n  await addTodo({name: 'new todo'});\n  expect(dbSetSpy).toHaveBeenCalledWith('todos:1', {name: 'new todo', id: 1});\n});\n\ntest('CommonJS \u003e getTodo \u003e returns output of db.get', async () =\u003e {\n  const dbGetSpy = jest.spyOn(db, 'get').mockResolvedValueOnce({\n    id: 1,\n    name: 'todo-1'\n  });\n\n  const expected = {\n    id: 1,\n    name: 'todo-1'\n  };\n  const actual = await getTodo(1);\n\n  expect(dbGetSpy).toHaveBeenCalledWith('todos:1');\n  expect(actual).toEqual(expected);\n});\n```\n\nNotice how we're not calling `jest.mock()`. Instead we're mocking/spying only a specific function of the module when we need to by modifying the `db` module implementation.\n\n#### ES6 Modules: Spy import/mock part of a module with Jest\n\n##### Default exports\n\nAssuming our `db.js` module exports in the following manner (see [examples/spy-module-esm-default/db.js](./examples/spy-module-esm-default/db.js)):\n```js\nconst data = {};\n\nasync function get(k) {\n  return data[k];\n}\n\nasync function set(k, v) {\n  data[k] = v;\n}\n\nconst db = {\n  get,\n  set\n};\n\nexport default db;\n```\n\nWe can then import it as follows (code listing lifted from [examples/spy-module-esm-default/lib.js](./examples/spy-module-esm-default/lib.js)):\n\n```js\nimport db from './db';\n\nconst keyPrefix = 'todos';\nconst makeKey = key =\u003e `${keyPrefix}:${key}`;\n\nlet autoId = 1;\n\nfunction addTodo(todo) {\n  const id = autoId++;\n  const insertable = {\n    ...todo,\n    id\n  };\n  return db.set(makeKey(id), insertable);\n}\n\nfunction getTodo(id) {\n  return db.get(makeKey(id));\n}\n\nconst lib = {\n  addTodo,\n  getTodo\n};\n\nexport default lib;\n```\n\nSpying on the import/mocking part of the module becomes possible in the following fashion (full code at [examples/spy-module-esm-default/lib.jest-test.js](./examples/spy-module-esm-default/lib.jest-test.js)):\n\n```js\nimport db from './db';\n\nimport lib from './lib';\n\nconst {addTodo, getTodo} = lib;\n\nbeforeEach(() =\u003e jest.clearAllMocks());\n\ntest('ESM Default Export \u003e addTodo \u003e inserts with new id', async () =\u003e {\n  const dbSetSpy = jest.spyOn(db, 'set').mockImplementationOnce(() =\u003e {});\n  await addTodo({name: 'new todo'});\n  expect(dbSetSpy).toHaveBeenCalledWith('todos:1', {name: 'new todo', id: 1});\n});\n\ntest('ESM Default Export \u003e getTodo \u003e returns output of db.get', async () =\u003e {\n  const dbGetSpy = jest.spyOn(db, 'get').mockResolvedValueOnce({\n    id: 1,\n    name: 'todo-1'\n  });\n\n  const expected = {\n    id: 1,\n    name: 'todo-1'\n  };\n  const actual = await getTodo(1);\n\n  expect(dbGetSpy).toHaveBeenCalledWith('todos:1');\n  expect(actual).toEqual(expected);\n});\n```\n\nNotice how we don't mock the `db` module with a `jest.mock()` call. Again we spy on the method that we're interested in stubbing/spying for a particular test.\n\nWe leverage `mockImplementationOnce()` to avoid calling the real function (which you might not always want to do).\n\n##### Named exports + \"import * as alias from 'module-name'\"\n\n\u003e Note: I've not read the full spec, the fact that this works might be a quirk of the Babel ES2015 module transpilation\n\nAssuming we've defined `db.js` as follows (using named exports, see the file at [examples/spy-module-esm-named/db.js](./examples/spy-module-esm-named/db.js)):\n\n```js\nconst data = {};\n\nexport async function get(k) {\n  return data[k];\n}\n\nexport async function set(k, v) {\n  data[k] = v;\n}\n```\n\nWe can import all the named exports under an alias with `import * as db from './db'` (code listing lifted from [examples/spy-module-esm-named/lib.js](./examples/spy-module-esm-named/lib.js)):\n```js\nimport * as db from './db';\n\nconst keyPrefix = 'todos';\nconst makeKey = key =\u003e `${keyPrefix}:${key}`;\n\nlet autoId = 1;\n\nexport function addTodo(todo) {\n  const id = autoId++;\n  const insertable = {\n    ...todo,\n    id\n  };\n  return db.set(makeKey(id), insertable);\n}\n\nexport function getTodo(id) {\n  return db.get(makeKey(id));\n}\n```\n\nThe calls to db.set and db.get can be spied/mocked using the following approach (full code test file at [examples/spy-module-esm-named/lib.jest-test.js](./examples/spy-module-esm-named/lib.jest-test.js)):\n\n```js\nimport * as db from './db';\n\nimport {addTodo, getTodo} from './lib';\n\nbeforeEach(() =\u003e jest.clearAllMocks());\n\ntest('ESM named export \u003e addTodo \u003e inserts with new id', async () =\u003e {\n  const dbSetSpy = jest.spyOn(db, 'set').mockImplementationOnce(() =\u003e {});\n  await addTodo({name: 'new todo'});\n  expect(dbSetSpy).toHaveBeenCalledWith('todos:1', {name: 'new todo', id: 1});\n});\n\ntest('ESM named export \u003e getTodo \u003e returns output of db.get', async () =\u003e {\n  const dbGetSpy = jest.spyOn(db, 'get').mockResolvedValueOnce({\n    id: 1,\n    name: 'todo-1'\n  });\n\n  const expected = {\n    id: 1,\n    name: 'todo-1'\n  };\n  const actual = await getTodo(1);\n\n  expect(dbGetSpy).toHaveBeenCalledWith('todos:1');\n  expect(actual).toEqual(expected);\n});\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhugodf%2Fmock-spy-module-import","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhugodf%2Fmock-spy-module-import","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhugodf%2Fmock-spy-module-import/lists"}