- 投稿日:
- まず
history.push('/path/to/dest')
自体のテストを書くことはないはずなので、何かしらの副作用として実行される事が前提です - testing-library.com に書いてあることの応用です
/**
* useHistory() を使えるようにするテストユーティリティ
*/
const renderWithRouter = (children: JSX.Element, { route = '/' } = {}) => {
window.history.pushState({}, 'Test page', route);
return render(children, {
wrapper: BrowserRouter,
});
};
// spy 用のモック関数
const mockPush = jest.fn();
// react-router-dom をモックにする
jest.mock('react-router-dom', () => ({
useHistory: () => ({
// モック関数を設定
push: mockPush,
}),
}));
describe('Bar', () => {
it('history.push のテスト', () => {
renderWithRouter(<Bar />, {
route: '/foo/bar',
});
// ここらへんに同期的に副作用を起こす処理を書く
// 以降、副作用で history.push('/foo/baz') されたとする
// 呼ばれたことの確認
expect(mockPush).toBeCalled();
// 引数の確認
expect(mockPush.mock.calls[0][0]).toBe('/foo/baz');
});
});
- 投稿日:
fs
とかchild_process
とかそういうやつをモックする方法- jest単体の機能では実現できないのでハマるポイント
- たぶん jest.MockedFunction でも同じことができる
サンプルコード
import { execSync } from 'child_process';
// まず全体をモックする
jest.mock('child_process');
// モックにする
const mockExecSync = execSync as jest.MockedFunction<typeof execSync>;
describe('execSync', () => {
it('spyOn execSync', () => {
// 対象をコール
execSync('echo 1');
// 通る
expect(mockExecSync).toHaveBeenCalled();
// 通る, echo 2とかにするとちゃんとコケてくれる
expect(mockExecSync).toHaveBeenCalledWith('echo 1');
});
});
- 投稿日:
スプレッド演算子で引き渡した内容の内、一部だけを利用するケースを想定
サンプルコード
検査対象
type FooBar = {
foo: string;
bar: number;
};
/**
* `foo` と `bar` しか使われない関数
* @param arg
*/
export const spreadExample = (arg: FooBar) => {
return new Promise((resolve) => {
resolve([arg.foo, arg.bar]);
});
};
テストコード
import * as spex from '../spreadExample';
const spiedSpreadExample = jest.spyOn(spex, 'spreadExample');
describe('spreadExample', () => {
it('example', async () => {
const test = {
foo: 'hoge',
bar: 123,
baz: true, // 今回の課題となる項目
};
// 余計な `baz` が流し込まれているため、
// 普通に検査しようとすると `baz` が邪魔で上手く行かないケース
await spex.spreadExample({ ...test });
expect(spiedSpreadExample).toBeCalled();
// コールバックで `expect.objectContaining()` を呼ぶことにより
// 見たい項目だけを検査することが可能(`baz` を見なくて済む
expect(spiedSpreadExample).toHaveBeenCalledWith(
expect.objectContaining({
foo: 'hoge',
bar: 123,
})
);
});
});
- 投稿日:
単体テストの観点でいうとprocess.argv
そのものはモックしないほうが良いと思っているので、本記事ではprocess.argv
自体をモックする方法と、それを回避する方法を紹介する
サンプルコード
正攻法
describe('example', () => {
afterEach(() => {
// 元に戻しておく
process.argv.length = 2;
});
it('got first param', () => {
process.argv.push('param1');
expect(process.argv.length).toBe(3);
expect(process.argv[2]).toBe('param1');
});
});
そもそもモックせずに済むように設計する
process.argv
を利用している関数でprocess.argv
を引数に取ればモック不要となる
const getArgv = (argv: string[]) => {
// some procedure
}
describe('getArgv', () => {
it('got first param', () => {
const argv = [,, 'param1'];
expect(argv.length).toBe(3);
expect(argv[2]).toBe('param1');
});
});