Example 1 :- Mocking Classes
//returnNameOrAge.js
export const returnNameOrAge = (isName) => {
  if (isName) {
    return "My Name is XYZ"
  }
  return 25
}
//someOtherFunction.js
class SomeModule {
  returnTrueOrFalse() {
    return false;
  }
}
export { SomeModule };
//index.js
import { returnNameOrAge } from "./returnNameOrAge";
import { SomeModule } from "./someOtherFunctions";
const someModule = new SomeModule();
export const testVitest = () => {
  const dataFromSomeModule = someModule.returnTrueOrFalse();
  const dataFromReturnNameOrAge = returnNameOrAge(dataFromSomeModule);
  return dataFromReturnNameOrAge;
};
//index.test.js
import { it, expect, describe, vi } from "vitest";
import { testVitest } from ".";
import { SomeModule } from "./someOtherFunctions";
vi.mock("./someOtherFunctions.js", async (importActual) => {
  const mod = await importActual();
  const SomeModule = vi.fn().mockReturnValue({
    returnTrueOrFalse: vi.fn(),
  });
  return {
    ...mod,
    SomeModule,
  };
});
describe("testVitest", () => {
  it("should return name", () => {
    const mockedSomeModule = new SomeModule();
    vi.mocked(mockedSomeModule.returnTrueOrFalse).mockReturnValue(true);
    const data = testVitest();
    expect(data).toBe("My Name is XYZ");
  });
  it("should return age", () => {
    const mockedSomeModule = new SomeModule();
    vi.mocked(mockedSomeModule.returnTrueOrFalse).mockReturnValue(false);
    const data = testVitest();
    expect(data).toBe(25);
  });
});
let's break down the modules and the test file
Modules:
- returnNameOrAge.js: This module defines a simple function named - returnNameOrAgethat takes a boolean (- isName) as input. If- isNameis true, it returns a string "My Name is XYZ". Otherwise, it returns the number 25.
- someOtherFunctions.js: This module defines a class named - SomeModule. The class has a method called- returnTrueOrFalsethat simply returns- false. This class is likely intended to be mocked in the test.
- index.js: This is the main module where everything comes together. It imports the - returnNameOrAgefunction and the- SomeModuleclass from the other modules. It then creates a new instance of- SomeModuleand defines a function called- testVitest. The- testVitestfunction calls the- returnTrueOrFalsemethod of the- someModuleinstance and then uses the return value to call the- returnNameOrAgefunction. Finally, it returns the result from- returnNameOrAge.
Test File (index.test.js):
This file uses the Vitest testing framework to test the testVitest function from index.js.
- Imports: It imports the necessary functions from Vitest ( - it,- expect,- describe, and- vi) for writing tests. It also imports the- testVitestfunction from- index.jsand the- SomeModuleclass from- someOtherFunctions.js.
- Mocking: It uses the - vi.mockfunction to mock the- someOtherFunctions.jsmodule. This means that when the test runs, it won't use the actual implementation of the- SomeModuleclass, but a mocked version instead. The mocked version is defined using a function that returns an object with a mocked- SomeModuleclass. The mocked- SomeModuleclass has a mocked- returnTrueOrFalsemethod that can be controlled by the test.
- 
Test Cases: The file defines two test cases using describeandit.- The first test case (it("should return name")) mocks thereturnTrueOrFalsemethod of the mockedSomeModuleto returntrue. It then calls thetestVitestfunction and asserts that the returned value is "My Name is XYZ" usingexpect.
- The second test case (it("should return age")) mocks thereturnTrueOrFalsemethod of the mockedSomeModuleto returnfalse. It then calls thetestVitestfunction and asserts that the returned value is 25 usingexpect.
 
- The first test case (
MAY I HAVE YOUR ATTENTION, PLEASE!!!
Even though index.js depends on both returnNameOrAge and SomeModule only SomeModule but not returnNameOrAge is mocked in the test, here are the reason :-
- Focus of the Test: The test aims to isolate the logic of - testVitestin- index.js. This function relies on- returnNameOrAgeto format the output based on the value received from- SomeModule. Since- returnNameOrAgeis a simple function with clear logic, mocking it might be unnecessary for this specific test.
- Mocking Complexity: Mocking a class like - SomeModuleallows for more control over its behavior. You can define what its methods return in different scenarios. In this case, the test wants to control the output of- returnTrueOrFalseto verify how- testVitesthandles different inputs. Mocking- returnNameOrAgewouldn't provide the same level of control.
- Testing vs. Implementation: Ideally, the functionality of - returnNameOrAgeshould be tested in its own dedicated test file. This keeps the tests focused and avoids redundancy. Mocking it in this test would be testing an implementation detail rather than the overall logic of- testVitest.
Example 2 :- Mocking Functions
//returnNameOrAge.js
export const returnNameOrAge = (isName) => {
  if (isName) {
    return "My Name is XYZ"
  }
  return 25
}
//someOtherFunction.js
export const someOtherFunction = () => {
  const testValue = true;
  return testValue;
};
//index.js
import { returnNameOrAge } from "./returnNameOrAge";
import { someOtherFunction } from "./someOtherFunctions";
export const testVitest = () => {
  const dataFromSomeOtherFunction = someOtherFunction();
  const dataFromReturnNameOrAge = returnNameOrAge(dataFromSomeOtherFunction);
  return dataFromReturnNameOrAge;
};
//index.test.js
import { it, expect, describe, vi } from "vitest";
import { testVitest } from ".";
const mocks = vi.hoisted(() => ({
  someOtherFunction: vi.fn(),
}));
vi.mock("./someOtherFunctions.js", () => ({
  someOtherFunction: mocks.someOtherFunction,
}));
describe("testVitest", () => {
  it("should return name", () => {
    mocks.someOtherFunction.mockReturnValue(true);
    const data = testVitest();
    expect(data).toBe("My Name is XYZ");
  });
  it("should return age", () => {
    mocks.someOtherFunction.mockReturnValue(false);
    const data = testVitest();
    expect(data).toBe(25);
  });
});
let's break down the modules and the test file
Modules:
- 
returnNameOrAge.js:
- This module defines a function named returnNameOrAgethat takes a boolean (isName) as input.
- If isNameis true, it returns the string "My Name is XYZ".
- Otherwise, it returns the number 25.
 
- This module defines a function named 
- 
someOtherFunctions.js:
- This module defines a function named someOtherFunction.
- This function simply creates a constant testValuewith the valuetrueand returns it.
 
- This module defines a function named 
- 
index.js:
- This is the main module.
- It imports returnNameOrAgefromreturnNameOrAge.jsandsomeOtherFunctionfromsomeOtherFunctions.js.
- It defines a function called testVitest.
- 
testVitestcallssomeOtherFunctionto get a value.
- It then calls returnNameOrAgewith the value fromsomeOtherFunctionand returns the result.
 
Test File (index.test.js):
This file uses the Vitest testing framework to test the testVitest function from index.js.
- 
Imports:
- It imports necessary functions from Vitest for writing tests (it,expect,describe, andvi).
- It imports the testVitestfunction fromindex.js.
 
- It imports necessary functions from Vitest for writing tests (
- 
Mocking: - It uses the vi.mockandvi.hoistedfunctions together to mock thesomeOtherFunction. Here's a breakdown:- 
vi.hoistedcreates a function that returns an object to hold mocks. This ensures mocks are created only once before each test.
- Inside vi.mock, it replaces thesomeOtherFunctionfromsomeOtherFunctions.jswith the mocked version from themocksobject.
 
- 
 
- It uses the 
- 
Test Cases: - The file defines two test cases using describeandit.- The first test ("should return name") mockssomeOtherFunctionto returntrue(usingmockReturnValue). It then callstestVitestand asserts the returned value is "My Name is XYZ" usingexpect.
- The second test ("should return age") mockssomeOtherFunctionto returnfalse. It then callstestVitestand asserts the returned value is 25 usingexpect.
 
- The first test (
 
- The file defines two test cases using 
Example 3 :- Actual Import Mocking and/or Hoisting+Mocking
Now, We'll write two unit tests for the same function, each leveraging a different mocking approach. The first test case will demonstrate mocking the actual import, while the second will explore the concept of hoisting combined with mocking. By comparing these techniques, you'll gain valuable insights into their strengths and how to choose the most suitable method for your specific testing needs.
// userService.js
import axios from "axios";
const userService = async () => {
  const { data } = await axios.get(
    "https://jsonplaceholder.typicode.com/users/1",
  );
  return data;
};
export default userService;
// approach involving hoisting and mocking (this approach doesn't involve importing axios in the test file)
import userService from "./userService";
const mockedAxios = vi.hoisted(() => ({
  default: {
    get: vi.fn(),
  },
}));
vi.mock("axios", () => ({
  default: mockedAxios.default,
}));
test("testing", async () => {
  mockedAxios.default.get.mockResolvedValue({
    data: {
      id: 1,
    },
  });
  const data = await userService();
  expect(data.id).toBe(1);
});
// approach involving mocking using importActual (this approach involve importing axios in the test file)
import axios from "axios";
import userService from "./userService";
vi.mock("axios", async () => {
  const axios = await vi.importActual("axios");
  const get = vi.fn();
  return {
    default: {
      ...axios,
      get,
    },
  };
});
test("testing", async () => {
  vi.mocked(axios.get).mockResolvedValue({
    data: {
      id: 1,
    },
  });
  const data = await userService();
  expect(data.id).toBe(1);
});
importActual can also be used as following as well
vi.mock("axios", async (importActual) => {
  const axios = await importActual<typeof import("axios")>();
  const get = vi.fn();
  return {
    default: {
      ...axios,
      get,
    },
  };
});
KEY TAKE AWAYS
- general use cases of - importActual:- class mocking, function mocking especially when these functions are spied on {- vi.spyOn()} (good use cases example for- spyOnwould be to unit test how many times the function has been executed)
- use case of - hoisting+mocking:- for general test cases
 
 
              
 
    
Top comments (0)