Can Vite mock a module outside of project dependencies?

482 Views Asked by At

I have a JS package that runs in an environment where require('custompackage') is injected. I want to make sure that when I run vitest that require('custompackage') points to my mock.

When I used Jest, I was able to mock this with config like this:

  moduleNameMapper: {
    '^custompackage$': '<rootDir>/../../dependency-mocks/custompackage.js',
  },

I am struggling to understand the conversion of code like this Vite.

I tried vitest config like this:

deps: {
  # i made a custompackage folder and put an index.js file within
  moduleDirectories: ['node_modules', resolve('./tests/dependency-mocks')],
},

The above deps I tried both in top level vitest config and within the test property. I made ./tests/dependency-mocks/custompackage/index.js along with a package.json to further try and spoof the module.

I also tried variations of alias and resolve.alias that pointed straight at index.js. No matter what I tried, I get Cannot find module 'custompackage'

Doing vi.mock('custompackage', () => {}) also seemed to have no effect. I believe it's because vitest would still try to find the real module before mocking, which is why I think that resolve is the answer. I just can't seem to crack the right combo.

Another attempt was via alias like this:

#tried both pointing at folder and specific file
const replacement = resolve(
  __dirname,
  './tests/dependency-mocks/custompackage',
);

....

  resolve: {
    alias: {
      entries: [{ find: 'custompackage', replacement }],
    },
  },

One quirk from my environment is that the things I am mocking with no issue are import X from 'package'; but these special ones are const x = require('custompackage');. I thought there possibly an issue with mocking when mixing import vs require, but I sanity checked it with an import instead and I got Failed to resolve import "custompackage"

Update I have created a StackBlitz at https://stackblitz.com/edit/vitejs-vite-aqrvdv?file=src%2Fhello.js

You can see my hello.js requires a package that is not in my dependency list, so there are no node modules. Despite calling vi.mock, it still has an error.

2

There are 2 best solutions below

0
On BEST ANSWER

I had to use commonjs specifically in a search and found out that vitest does not support mocking require calls.

https://github.com/vitest-dev/vitest/discussions/3134

You can install https://www.npmjs.com/package/mock-require to make tests work as expected.

1
On

vi.mock or jest.mock only going to work if you are using that import inside the test file. If your test function is dependent on another function outside that file the mock won't work unless you do it in a global state.

You can use setupFiles or setupFilesAfterEnv

It can be used as follows:

// Jest config
{
  ...
  setupFiles: ['pathTo/custompackage.js'],
  ...
}

Vitest setup

// vite.config.js
{
  ...

  test: {
    ...
    setup: ['pathTo/custompackage.js']
    ...
  }

  ...
}

In your setup file, you can mock the import and swap it with whatever you want.

// setup file
vi.mock('custompackage', vi.importActual('mockedCustomPackage'))

importActual