✅ はじめに
vitestでテスト対象がimportしてるモジュールをモックする方法について、サラッと知りたい人向けの記事です。
✅ サンプルコード
// foo/index.ts
// barをimport
import { bar } from '../bar'
// bar()を実行して、文字列「foo-->」の後ろに付けて返す
export const foo = (): string => {
return 'foo-->' + bar()
}
// bar/index.ts
// 文字列「bar」を返す
export const bar = (): string => {
return 'bar'
}
✅ モックしない場合
// foo/index.test.ts
// テスト用の関数をimport
import { describe, expect, test } from 'vitest'
// テスト対象モジュールをimport
import { foo } from '.'
// テスト
describe('テスト', () => {
test('foo', () => {
// foo()を実行する
const result = foo()
// 結果が「foo-->bar」であること
expect(result).toBe('foo-->bar')
})
})
✅ vi.spyOnでモックする場合
// foo/index.test.ts
// テスト用の関数をimport
import { describe, expect, test, vi } from 'vitest'
// テスト対象モジュール
import { foo } from '.'
// モック対象モジュール
import * as barModule from '../bar'
// テスト
describe('同期関数', () => {
test('foo', () => {
// bar()をモックする
const barSpy = vi.spyOn(barModule, 'bar').mockReturnValue('mock');
// foo()を実行する
const result = foo();
// 結果が「foo-->mock」であること
expect(result).toBe('foo-->mock');
expect(barSpy).toHaveBeenCalledWith(1);
expect(barSpy).toHaveBeenCalledTimes(1);
// モックをリセット
barSpy.mockRestore();
})
})
✅ vi.mockでモックする場合
📝 パターン1:戻り値が固定で良い場合
// foo/index.test.ts
// テスト用の関数をimport
import { describe, expect, test, vi } from 'vitest'
// テスト対象モジュールをimport
import { foo } from '.'
// barをモックして、「mock」を返すようにする
vi.mock('../bar', () => ({
bar: vi.fn(() => 'mock')
}))
// テスト
describe('テスト', () => {
test('foo', () => {
// foo()を実行する
const result = foo()
// 結果が「foo-->mock」であること
expect(result).toBe('foo-->mock')
})
})
📝 パターン2:戻り値をテスト内で設定する場合
// foo/index.test.ts
// テスト用の関数をimport
import { describe, expect, test, vi } from 'vitest'
// テスト対象モジュールをimport
import { foo } from '.'
// モック対象モジュールをimport
import { bar } from '../bar'
// barをモックして、Mock型で定義しておく
// (戻り値は設定しない)
vi.mock('../bar');
const barMock = bar as Mock;
// テスト
describe('テスト', () => {
test('foo', () => {
// モックに戻り値を設定する
barMock.mockReturnValue('mock')
// foo()を実行する
const result = foo()
// 結果が「foo-->mock」であること
expect(result).toBe('foo-->mock')
})
})
📝 モック関数
モック対象が同期関数の場合
// モック対象が同期関数の場合
xxxMock.mockReturnValue('mock')
//=> モックは'mock'を返す
モック対象が非同期関数の場合
// モック対象が非同期関数の場合
xxxMock.mockResolvedValue('mock')
//=> モックは'mock'を返す
モックに引数を渡したい場合
// モックに引数を渡したい場合
xxxMock.mockImplementation((i) => 'mock'.repeat(i))
// モックに引数「1」が渡された場合、モックは'mock'を返す
// モックに引数「2」が渡された場合、モックは'mockmock'を返す