2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

jestでNumber of calls: 0となり、関数が実行されない

2
Last updated at Posted at 2024-09-19

はじめに

jestでtestを行っている際に、関数が実行されず、テストが失敗しました。
解決まで、時間をとられたので解決策をまとめようと思います。

事象

新規登録ページを作成し、そのテストを行いました。
すると以下のエラーが発生しました。

expect(jest.fn()).toHaveBeenCalledWith(...expected)

Expected: "山田太郎", "1"

Number of calls: 0

期待する引数と、受け取った引数があっていないというエラーです。

該当コード

コード一部抜粋

<form onSubmit={handleSubmit(onSubmit)}>
  <FormControl mb={4} isInvalid={!!errors.description}>
    <FormLabel>名前 <span style={{ color: 'red' }}>*</span></FormLabel>
    <Textarea
      placeholder="山田太郎"
      {...register("name", {
        required: "必須項目です"
      })} />
    <FormErrorMessage>{errors.description?.message}</FormErrorMessage>
  </FormControl>
  <FormControl mb={4} isInvalid={!!errors.select}>
    <FormLabel>セレクトボックス <span style={{ color: 'red' }}>*</span></FormLabel>
      <Select
        placeholder='選択してください'
        {...register("select", {
          required: "必須項目です"
        })} >
        {selects?.map((select) => (
          <option key={select.id} value={select.id}>{select.name}</option>
        ))}
      </Select>
    <FormErrorMessage>{errors.select?.message}</FormErrorMessage>
  </FormControl>
  <Button isLoading={loading} type="submit" colorScheme='teal' data-testid="submit" mx={4} mb={4}>登録</Button>
</form>

このテストを実行しました。
fireEvent.changeで値を入力、fireEvent.clickでsubmitボタンをクリック。

it("登録できること", async () => {
  render(
    <CardRegister />
  );

  fireEvent.change(screen.getByLabelText('名前', { exact: false }), { target: { value: '山田太郎' } });
  fireEvent.change(screen.getByLabelText('セレクトボックス', { exact: false }), { target: { value: '1' } });

  fireEvent.click(screen.getByTestId('submit'));

  await waitFor(() => {
    expect(addUser).toHaveBeenCalledWith(
      '山田太郎',
      '1',
    );
});

原因

原因は簡単で、入力がうまくできておらず、バリデーションエラーで引っかかっていました。
セレクトボックスをsupabaseというDBから、非同期でデータを取得しているのですが、データ取得前にfireEvent.changeを入力してしまっていました。
value: '1'はその段階では存在しないので、選択されず、バリデーションエラーが発生しました。

フォーム項目を非同期で取得していることを失念していました、、

解決策

セレクトボックスのフォームにdata-testidを追加

<FormLabel>セレクトボックス <span style={{ color: 'red' }}>*</span></FormLabel>
  <Select
    placeholder='選択してください'
    data-testid="select" // 追加
    {...register("select", {
      required: "必須項目です"
    })} >
    {selects?.map((select) => (
      <option key={select.id} value={select.id}>{select.name}</option>
    ))}
  </Select>
<FormErrorMessage>{errors.select?.message}</FormErrorMessage>

入力を非同期に変更
findByTestIdで非同期取得にして、awaitをつけてあげます。

it("登録できること", async () => {
  render(
    <CardRegister />
  );

  fireEvent.change(screen.getByLabelText('名前', { exact: false }), { target: { value: '山田太郎' } });
      fireEvent.change(await screen.findByTestId('select'), { target: { value: "1" } });

  fireEvent.click(screen.getByTestId('submit'));

  await waitFor(() => {
    expect(addUser).toHaveBeenCalledWith(
      '山田太郎',
      '1',
    );
});

まとめ

toHaveBeenCalledWithでエラーが起きたら、モックができていないか、非同期部分でバリデーションエラーにひっかかってないか疑うのが良いでしょう。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?