Vitest 模拟模块仅在一项测试中起作用,并在其他测试中使用实际功能

flo*_*aun 11 javascript unit-testing nuxt.js vitest

以下是我的问题的抽象,因此没有太大意义:

假设我有一个简单的实用程序callMethodIf,它返回另一个导入方法 ( blackbox) 的返回值。

~~/utils/call-method-if.js:

import { blackbox } from '~~/utils/blackbox';

export const callMethodIf = (condition) => {
    return blackbox(condition);
};
Run Code Online (Sandbox Code Playgroud)

~~/utils/blackbox.js:

export const blackbox = (condition) => {
    return { called: condition };
};
Run Code Online (Sandbox Code Playgroud)

我将如何运行一个测试用例来调用 的实际实现blackbox(),以及另一个测试用例来模拟 的返回值blackbox()

我尝试这样做:

import { describe, expect, it } from 'vitest';

import { callMethodIf } from '~~/utils/call-method-if';

describe('Call method if', () => {
    it('returns "called: true" if condition is true', () => {
        const result = callMethodIf(true);
        expect(result).toEqual({ called: true });
    });

    it('returns mocked blackbox return object', () => {
        vi.mock('~~/utils/blackbox', () => ({
            blackbox: vi.fn().mockReturnValue({ mock: true })
        }));
        const result = callMethodIf(false);
        expect(result).toEqual({ mock: true });
    });
});
Run Code Online (Sandbox Code Playgroud)

如果我只运行其中一个测试,这两个测试都会起作用,但组合起来时它们就不起作用。

跑步vi.clearAllMocks()或者vi.resetAllMocks()没有帮助。

在我的第一个测试中定义全局模拟并覆盖它也不起作用:

import { describe, expect, it } from 'vitest';

import { callMethodIf } from '~~/utils/call-method-if';

vi.mock('~~/utils/blackbox', () => ({
    blackbox: vi.fn().mockReturnValue({ mock: true })
}));

describe('Call method if', () => {
    it('returns "called: true" if condition is true', () => {
        vi.mock('~~/utils/blackbox', async () => ({
            blackbox: (await vi.importActual('~~/utils/blackbox')).blackbox
        }));
        const result = callMethodIf(true);
        expect(result).toEqual({ called: true });
    });

    it('returns mocked blackbox return object', () => {
        const result = callMethodIf(false);
        expect(result).toEqual({ mock: true });
    });
});
Run Code Online (Sandbox Code Playgroud)

flo*_*aun 12

好吧,经过多次尝试和错误,我终于成功了。我真的不知道为什么我之前的尝试不起作用。

工作解决方案:

import { describe, expect, it } from 'vitest';

import { callMethodIf } from '~~/utils/call-method-if';

vi.mock('~~/utils/blackbox');

describe('Call method if', () => {
    it('returns "called: true" if condition is true', async () => {
        const blackbox = await import('~~/utils/blackbox');
        blackbox.blackbox = (await vi.importActual('~~/utils/blackbox')).blackbox;
        const result = callMethodIf(true);
        expect(result).toEqual({ called: true });
    });

    it('returns mocked blackbox return object', async () => {
        const blackbox = await import('~~/utils/blackbox');
        blackbox.blackbox = vi.fn().mockReturnValue({ mock: true });
        const result = callMethodIf(false);
        expect(result).toEqual({ mock: true });
    });
});
Run Code Online (Sandbox Code Playgroud)

使用 TypeScript 时,请考虑importActual()像这样输入 return:

blackbox.blackbox = (await vi.importActual<typeof import('~~/utils/blackbox')>('~~/utils/blackbox')).blackbox;
Run Code Online (Sandbox Code Playgroud)


Joe*_*ven 6

我在使用Vite的时候也遇到过这个问题。经过大量的尝试和错误后,我成功地通过使用以下代码来模拟模块函数:

vi.mock('@/models/generated/graphql')

describe('MyComponent works as expected', () => {
  it('Shows loading when loading', async () => {
    const graphql = await import('@/models/generated/graphql')
    graphql.useGetAllQuery = vi.fn().mockReturnValue({ loading: true, error: null, data: null })

    render(<MyComponent />)

    expect(screen.findByTestId('my-component-loading')).toBeTruthy()
  })
}
Run Code Online (Sandbox Code Playgroud)

我正在嘲笑的函数是这个(它是为我的 Graphql 服务自动生成的):

export function useGetAllQuery(baseOptions?: Apollo.QueryHookOptions<GetAllQuery, GetAllQueryVariables>) {
        const options = {...defaultOptions, ...baseOptions}
        return Apollo.useQuery<GetAllQuery, GetAllQueryVariables>(GetAllDocument, options);
      }
Run Code Online (Sandbox Code Playgroud)

我不太明白为什么会这样,但确实如此。我希望这段代码片段可以帮助一些人。