はじめに
Reactでログイン処理を行う上でRecoilを使うことになりました
その後、今まで動いていたテストが動かなくなりましたので解決方法をまとめます
問題
ログインAPIを叩くカスタムフックを作成して、成功したらログイン済みを表すisLogin
のステートをtrue
にする処理をRecoil
を使って行いました
すると以下のように書いていたテストが通らなくなりました
test.tsx
describe("useSignInlogin", () => {
it("トップページに遷移すること", async () => {
const response = {
data: {
token: "12345",
},
};
mock.onPost(`http://localhost:8080/sign_in`).reply(200, response);
const { result } = renderHook(() => useSignIn());
await act(async () => {
result.current.login("test@example.com", "password");
});
expect(mockedNavigator).toHaveBeenCalledWith("/");
});
エラーをみるとテストが途中で失敗していそうでした
解決方法
そこで、Recoilでステートを更新する処理をコメントにするとテストがうまく動いていました
原因はRecoil
で参照しているatoms
が参照できないことでした
<RecoilRoot>
を利用して囲んだ箇所で利用できるのですが、カスタムフックだけをテストしているこのコードでは参照先がわからずエラーになります
ですので、テストを実行するカスタムフックを一時的に<RecoilRoot>
でラップするように修正しました
test.tsx
describe("useSignInlogin", () => {
it("トップページに遷移すること", async () => {
const response = {
data: {
token: "12345",
},
};
mock.onPost(`http://localhost:8080/sign_in`).reply(200, response);
const { result } = renderHook(() => useSignIn(), {
wrapper: RecoilRoot, # 追加
});
await act(async () => {
result.current.login("test@example.com", "password");
});
expect(mockedNavigator).toHaveBeenCalledWith("/");
});
するとテストが通るようになりました
おわりに
Recoilを初めて使うときに初心者がつまづきそうなエラーでした
公式ドキュメントを読みましょう
参考