skip to Main Content

I have three files:

  • use-user-info.ts
  • user-info.tsx
  • user-info.test.tsx

I want to test the behaviour of the component UserInfo (exported from user-info.tsx).

On my test file I mock the hook like this:

vi.mock("@/use-user-info");
describe(() => {
 beforeEach(() => {
  vi.mocked("@/use-user-info").mockReturnValue({
   userId: 1,
   username: "John Doe",
   isLoading: false
  })
  return () => {vi.clearAllMock()}
 })
})

The problem is that if I use the hook on the beforeEach scope, I got the mocked values, but if I put a console.log on user-info.tsx to know the value of the hook, I got "default values".

Reading the docs I think could be something related to mocking pitfalls, but cant see the problem.

My use-user-info implementation is something like this:

export const useUserInfo = (userId) => {
 const { infoNotification } = useNotification();
 const { updateUser } = useUpdateUser(updateBudgetData)
 const userMessages = useUserMessages(userId);

 return {
  infoNotification,
  updateUser,
  userMessages
 }
}

I tried to mock the hook on different forms:

  • vi.mock
  • vi.doMock
  • mockReturnValue
  • mockImplementation
  • Add the mock implementation on vi.mock
  • Add the mock implementantion after the vi.mock

I have the same error with similar hooks.

2

Answers


  1. Chosen as BEST ANSWER

    Trying things I discovered that the problem was that I mocked a module on the vitest.setup.tsfile. This module wasn't related with the hook I was trying to mock but commenting it, the problem solves. In this issue the user has the same problem as me and I solved it like in this comment, putting vi.resetModules(); at the bottom of vitest.setup.ts file.


  2. It sounds like the issue might be related to how the hook is being mocked and when the mock is being applied. Here’s a breakdown of what might be happening and how to fix it.

    • The mock might not be applied correctly before the component is rendered in your tests. This can happen if the mock is defined after the component has already used the original hook.
    • Ensure that the import path in your mock statement matches exactly how it’s imported in user-info.tsx. Even a slight difference can cause the mock to not be applied correctly.

    Place the vi.mock call outside of any test or lifecycle function to ensure the mock is applied before any component rendering or test execution. Like this:

    import { useUserInfo } from "@/use-user-info";
    import { vi } from "vitest";
    
    vi.mock("@/use-user-info");
    
    describe("UserInfo Component", () => {
      beforeEach(() => {
        vi.mocked(useUserInfo).mockReturnValue({
          userId: 1,
          username: "John Doe",
          isLoading: false,
        });
      });
    
      it("should display the user info", () => {
        // Your test implementation here
      });
    });
    

    If useUserInfo relies on other hooks or complex logic, and these dependencies affect the return values, ensure they are also mocked. To handle this, use mockImplementation to provide a more detailed mock:

    vi.mocked(useUserInfo).mockImplementation(() => ({
      userId: 1,
      username: "John Doe",
      isLoading: false,
      // Mock other internal hooks or logic here if needed
    }));
    

    While your beforeEach includes vi.clearAllMocks(), ensure it’s correctly placed after your tests to clean up any mocks that could interfere with subsequent tests.

      afterEach(() => {
        // Clearing all mocks and resetting modules after each test to avoid state leakage
        vi.clearAllMocks();
        vi.resetAllMocks();
        vi.restoreAllMocks();  // Optional: Restores the original implementations
      });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search