Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

197
Views
Spying On/Mocking Import of an Import

I'm writing unit tests using vitest on a VueJS application.

As part of our application, we have a collection of API wrapper services, e.g. users.js which wraps our relevant API calls to retrieve user information:

import client from './client'

const getUsers = () => {
   return client.get(...)
}

export default {
   getUsers
}

Each of these services utilise a common client.js which in turn uses axios to do the REST calls & interceptor management.

For our units tests, I want to check that the relevant url is called, so want to spy on, or mock, client.

I have followed various examples and posts, but struggling to work out how I mock an import (client) of an import (users.js).

The closest I've been able to get (based on these posts - 1, 2) is:

import { expect, vi } from 'vitest'
import * as client from '<path/to/client.js>'
import UsersAPI from '<path/to/users.js>'

describe('Users API', () => {
    beforeEach(() => {
        const spy = vi.spyOn(client, 'default')    // mock a named export
        expect(spy).toHaveBeenCalled() // client is called at the top of users.js
    })

    test('Users API.getUsers', () => {
        UsersAPI.getUsers()
        expect(spy).toHaveBeenCalled()
    })
})

but it's tripping on:

 ❯ async frontend/src/api/client.js:3:31
      2| import store from '@/store'
      3| 
      4| const client = axios.create({
       |                              ^
      5|     headers: {
      6|         'Content-Type': 'application/json'

where it's still trying to load the real client.js file.

I can't seem to mock client explicitly because the import statements run first, and so client is imported inside users.js before I can modify/intercept it. My attempt at the mocking was as follows (placed between the imports and the describe):

vi.mock('client', () => {
    return {
        default: {
            get: vi.fn()
        }
    }
})
about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

Mocking a module

vi.mock()'s path argument needs to resolve to the same file that the module under test is using. If users.js imports <root>/src/client.js, vi.mock()'s path argument needs to match:

// users.js
import client from './client' // => resolves to path/to/client.js
// users.spec.js
vi.mock('../../client.js')    // => resolves to path/to/client.js

It often helps to use path aliases here.

Spying/mocking a function

To spy on or mock a function of the mocked module, do the following in test():

  1. Dynamically import the module, which gets the mocked module.
  2. Mock the function off of the mocked module reference, optionally returning a mock value. Since client.get() returns axios.get(), which returns a Promise, it makes sense to use mockResolvedValue() to mock the returned data.
// users.spec.js
import { describe, test, expect, vi } from 'vitest'
import UsersAPI from '@/users.js'

vi.mock('@/client')

describe('Users API', () => {
  test('Users API.getUsers', async () => {
    1️⃣
    const client = await import('@/client')

    2️⃣
    const response = { data: [{ id: 1, name: 'john doe' }] }
    client.default.get = vi.fn().mockResolvedValue(response)
    
    const users = await UsersAPI.getUsers()
    expect(client.default.get).toHaveBeenCalled()
    expect(users).toEqual(response)
  })
})

demo

about 4 years ago · Juan Pablo Isaza Report

0

I've accepted the above answer, as that did address my initial question, but also wanted to include this additional step I required.

In my use case, I need to mock an entire module import, as I had a cascading set of imports on API files that in turn, imported more and more dependencies themselves.

To cut this, I found this in the vuex documentation about mocking actions:

https://vuex.vuejs.org/guide/testing.html#testing-actions

which details the use of webpack and inject-loader to substitute an entire module with a mock, preventing the source file loading at all.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!