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
).
~~/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()
?
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.
Defining a global mock and overwriting it in my first test doesn’t work either:
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 }); }); });
Advertisement
Answer
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:
blackbox.blackbox = (await vi.importActual<typeof import('~~/utils/blackbox')>('~~/utils/blackbox')).blackbox;