Vitest mock modules function in only one test and use the actual function in others

题意:

将 Vitest 的模块函数仅在一个测试中进行 mock,其余测试中使用实际函数。

问题背景:

The following is an abstraction of my problem and thus does not make too much sense:

以下是我问题的抽象,因此并没有太多意义。

Given I have a simple utility callMethodIf that's returning the return of another imported method (blackbox).

假设我有一个简单的工具函数 callMethodIf,它返回另一个导入方法(黑盒)的返回值。

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

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

export const callMethodIf = (condition) => {
    return blackbox(condition);
};

~~/utils/blackbox.js:

export const blackbox = (condition) => {
    return { called: condition };
};

How would I run one test case which calls the actual implementation of blackbox() and another one where I mock the return value of blackbox()?

我如何运行一个测试用例,调用 blackbox() 的实际实现,以及另一个测试用例,在其中我 mock 了 blackbox() 的返回值?

I tried to do it that way:        我尝试以这种方式进行操作:

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 });
    });
});

Both tests work if I run only one of them, but they don't work when combined.

如果我只运行其中一个测试,它们都能正常工作,但当它们结合在一起时就无法正常工作。

Running vi.clearAllMocks() or vi.resetAllMocks() don't help.

运行 vi.clearAllMocks()vi.resetAllMocks() 并没有帮助。

Defining a global mock and overwriting it in my first test doesn't work either:

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

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 });
    });
});

问题解决:

Okay, after lots of trial and error I finally got it to work. I can't really tell why my previous tries do not work tough.

好吧,经过大量的试错,我终于让它正常工作了。不过我确实不清楚为什么我之前的尝试没有成功。

Working solution:        可行的解决方案:

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 });
    });
});

When using TypeScript consider typing the importActual() return like that:

在使用 TypeScript 时,考虑像这样为 importActual() 的返回值指定类型:

blackbox.blackbox = (await vi.importActual<typeof import('~~/utils/blackbox')>('~~/utils/blackbox')).blackbox;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

营赢盈英

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值