Skip to content

SunsetFi/vitest-class-method-name-collision

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

This repo demonstrates a name collision bug with vitest 4.1.3

The test is triggered with the following conditions:

  • Using typescript
  • With "useDefineForClassFields" turned on in the tsconfig
  • Mocking a class with a method
  • In a file that imports a function whose name matches the method

Given a test that looks like this:

const { myMethodMock } = vi.hoisted(() => ({
  myMethodMock: vi.fn(),
}));

vi.mock("./MyClass", () => ({
  MyClass: class {
    myMethod = myMethodMock;
  },
}));

import { myMethod } from "./my-method";

describe("myMethod", () => {
  it("should call MyClass.myMethod", () => {
    myMethodMock.mockReturnValue("Mocked Hello, World!");
    const result = myMethod();
    expect(myMethodMock).toHaveBeenCalled();
    expect(result).toBe("Mocked Hello, World!");
  });
});

vitest gets confused and thinks the myMethod property key of MyClass in the mock is referencing the myMethod function imported from ./my-method. As a result, it tries to hoist the import above the mock in a way where myMethod is accessed as a property from the imported module. This causes a ReferenceError for an uninitialized property access, as ./my-method depends on the ./MyClass mock, which hasn't had a chance to run yet.

A workaround is to enclose the class property in a computed property syntax:

vi.mock("./MyClass", () => ({
  MyClass: class {
    ["myMethod"] = myMethodMock;
  },
}));

About

Demonstrates a vitest bug using typescript, useDefineForClassFields, and a method name matching a class method

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors