はじめに
タイトルどおりですが、モック化した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");
});
});