In Vitest, Order Of Import Matters For Mocks

2025-02-06
Vitest
Unit Testing
Javascript
Typescript
Software Development

Cutting to the chase

In Vitest, this would work:

    import {test, expect, vi} from "vitest";
    import round from "lodash.round";
    
    vi.mock("lodash.round", () => {
        return {
            default: (value) => 33
        }
    })
     
    test("roundup", () => {
        const no = 5.7;
        expect(round(no)).toBe(33);
    });

however if the mock is extracted to another file (say, to be reused across several tests), test will fail if it's imported after actual package it mocks:

    import {test, expect, vi} from "vitest";
    import round from "lodash.round";
    import _ from "./roundmock";
    
    test("roundup", () => {
        const no = 5.7;
        expect(round(no)).toBe(33);
    });

because the mock is imported after the actual package. This, however, will pass (note that the only difference is the order of imports):

    import {test, expect, vi} from "vitest";
    import _ from "./roundmock";
    import round from "lodash.round";
    
    test("roundup", () => {
        const no = 5.7;
        expect(round(no)).toBe(33);
    });

I guess that's because Vitest is hoisting mocks withing the file to happen before the imports, but if they're in separate files - the import will happen in actual import order.