Search code examples
unit-testingvue.jsjestjsmockingvuex

jest manual ES6 class mock is not active and I want to understand why


I am having problems using Jest manual mocks (the one in a parallel __mocks__ directory) in my project.

I think I understand how to use it and it actually works fine if I remove a single line in a file specified in the Jest setupFiles array.

In that file a global helper is installed (into global.createComp) that uses the vuex store.

This is a vue + vuex project but even running the stripped down spec using only jest gives unexpected results.

Can somebody look at my minimal reproducible example repo at https://github.com/thenoseman/jest-manual-mock-not-working, do a npm i and npm run test:unit and help me understand why the mock is not active?

You can find the line that need to be commented out in test/unit/support/helpers.js. Also the README shows a screenshot and further explains what the problem looks like.


Solution

  • setupFiles are evaluated before test files. As the reference states,

    A list of paths to modules that run some code to configure or set up the testing environment. Each setupFile will be run once per test file. Since every test runs in its own environment, these scripts will be executed in the testing environment immediately before executing the test code itself.

    JavaScript modules are evaluated once on first import. Importing @/store/modules/internetAtHome in helpers.js results in importing original @/api/DslService.

    The mock in test file doesn't affect @/api/DslService because it has already been evaluated earlier:

    jest.mock("@/api/DslService");
    import DslService from "@/api/DslService";
    

    In case helpers.js needs mocked @/api/DslService, jest.mock needs to be moved there.

    In case helpers.js needs original @/api/DslService but tests need mocked one, the module (and any module that depends on it) needs to be re-imported with jest.resetModules or jest.isolatedModules:

    jest.mock('@/api/DslService');
    
    let DslService;
    jest.isolateModules(() => {
      DslService = require("@/api/DslService").default;
    });
    ...
    

    For a module that was imported with original implementation and needs to be re-imported as a mock, jest.requireMock can be used, it doesn't need jest.mock('@/api/DslService'):

    let DslService = jest.requireMock("@/api/DslService").default;
    ...