はじめに
タイトルどおりですが、モック化したuseRecoilValueやuseRecoilStateの戻り値がundefinedになってしまう現象に遭遇し、小一時間ハマってしまいました。
jest 初心者なので勉強がてらメモを残します。
解決策
後に再現コードを記載しますが、先に結果を知りたい人用に解決策を記載します。
結論としては、以下の 2 点が解決策となります。
- 各テストケースごとに
mockImplementationを書く -
beforeEachにmockImplementationを書く
beforeEachと似た関数にbeforeAllがありますが、こちらはうまく動作しませんでした。
公式ドキュメント:beforeAll(fn, timeout)、beforeEach(fn, timeout)
再現コード
テスト対象のコンポーネントは成功、失敗に関わらず同一です。
テスト対象
import { atom, useRecoilValue } from "recoil";
const store = atom({
key: "store",
default: "default value",
});
function App() {
const state = useRecoilValue(store);
return (
<div>
<p id="test-element-1">{state}</p>
</div>
);
}
export default App;
うまくいったケース
テストコード
import { useRecoilValue } from "recoil";
import { shallow } from "enzyme";
import App from "./App";
jest.mock("recoil");
describe("各テストケースごとに mockImplementation を書く", () => {
test("recoilテスト", () => {
useRecoilValue.mockImplementation(() => "test value");
const result = shallow(<App />);
expect(result.find("#test-element-1").text()).toEqual("test value");
});
});
describe("beforeEach に mockImplementation を書く", () => {
beforeEach(() => {
useRecoilValue.mockImplementation(() => "test value");
});
test("recoilテスト", () => {
const result = shallow(<App />);
expect(result.find("#test-element-1").text()).toEqual("test value");
});
});
うまくいかなかったケース
いずれもstateの中身がundefinedになっています。
ケース① - jest.mockでuseRecoilValueをモック化する
テストコード
import { shallow } from "enzyme";
import App from "./App";
jest.mock("recoil", () => ({
...jest.requireActual("recoil"),
useRecoilValue: jest.fn(() => "test value"),
}));
describe("jest.mock で useRecoilValue をモック化する", () => {
test("recoilテスト", () => {
const result = shallow(<App />);
expect(result.find("#test-element-1").text()).toEqual("test value");
});
});
ケース② - beforeAllにmockImplementationを書く
テストコード
import { useRecoilValue } from "recoil";
import { shallow } from "enzyme";
import App from "./App";
jest.mock("recoil");
describe("beforeAll に mockImplementation を書く", () => {
beforeAll(() => {
useRecoilValue.mockImplementation(() => "test value");
});
test("recoilテスト", () => {
const result = shallow(<App />);
expect(result.find("#test-element-1").text()).toEqual("test value");
});
});