题意:
将 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;