質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
ユニットテスト

ユニットテストは、システムのテスト手法の一つで、個々のモジュールを対象としたテストの事を指します。対象のモジュールが要求や性能を満たしているか確認する為に実行します。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

1回答

2880閲覧

setStateを渡された子コンポーネントのテストの書き方

R-Fujimoto

総合スコア13

ユニットテスト

ユニットテストは、システムのテスト手法の一つで、個々のモジュールを対象としたテストの事を指します。対象のモジュールが要求や性能を満たしているか確認する為に実行します。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

1クリップ

投稿2020/02/14 08:55

stateとsetState渡した子コンポーネントのテストで、setStateのpropsの書き方が分からず困っています。

下記のデモは親コンポーネントでstateを管理し、子コンポーネントでstateを操作しているデモです。
テストファイルは、/src/__test__/Input.spec.tsxです。
demo

テスト用のpropsのsetStateの書き方をご教示いただけないでしょうか。

CodeSandboxではエラーが表示されつつも動いていますが、私が使用しているVSCodeだとsetStateを使うかはともかくpropsを全て設定しないとエラーによりコンパイルができない状況です。

使用しているツール

  • React.js
  • Jest
  • React Testing Library
  • TypeScript

ソースコード

Input.spec.tsx

tsx

1import React from "react"; 2import "@testing-library/jest-dom/extend-expect"; 3import { render, cleanup } from "@testing-library/react"; 4 5import Input from "../Input"; 6 7describe("Input", () => { 8 afterEach(cleanup); 9 const props = { 10 currentNum: 0 /* , 11 setCurrentNum: */ 12 }; 13 14 it("render set number", () => { 15 const { getByTestId } = render(<Input {...props} />); 16 expect(getByTestId("current-num")).toHaveTextContent( 17 "current set number: 0" 18 ); 19 }); 20 // it("setCurrentNum", () => { 21 22 // }); 23}); 24

Input.tsx

tsx

1import React, { useState } from "react"; 2 3type InputProps = { 4 currentNum: number; 5 setCurrentNum: React.Dispatch<React.SetStateAction<number>>; 6}; 7const Input: React.FC<InputProps> = ({ currentNum, setCurrentNum }) => { 8 const [inputNumber, setInputNumber] = useState(0); 9 10 return ( 11 <> 12 <input 13 type="number" 14 onChange={(e: React.ChangeEvent<HTMLInputElement>) => { 15 setInputNumber(Number(e.target.value)); 16 }} 17 /> 18 <button onClick={() => setCurrentNum(inputNumber)}>set number</button> 19 <p data-testid="current-num">current set number: {currentNum}</p> 20 </> 21 ); 22}; 23 24export default Input; 25

試したこと

tsx

1const props = { 2 currentNum: 0, 3 setCurrentNum: useState()[1] 4}

と書いてみたものの、

Invalid hook call. Hooks can only be called inside of the body of a function component. This ...

関数のトップレベルで使用しなければならないhooksのルールにより、上記のエラーが表示されます。

調べたこと

「testing-library setState props」で検索したところ、下記のページを見つけました。
How to setState in react-testing-library - Stack Overflow
Google翻訳によって翻訳したものの意味がよく分からなかったのですが、「テストでsetStateを使用するのはやめたほうがよい」と読み取りました。

とはいえsetStateをテストで使用せずとも、propsでsetStateを設定しないと、エラーが解決できない状況です。

今日初めてテストを書き始めたので、頓珍漢なコードを書いている可能性が大いにありますが、ご教示いただけますと幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hoshi-takanori

2020/02/15 00:53

InputProps の setCurrentNum の型ですが、Input の中では number しか渡さないので、React.Dispatch<number> または (value: number) => void でよいのでは?
guest

回答1

0

ベストアンサー

InputProps の setCurrentNum の型ですが、React.Dispatch<React.SetStateAction<number>> というのは (value: number | ((prevState: number) => number)) => void、つまり number または更新関数(古い値を受け取って新しい値を返す関数)を受け取って void を返す型になってます。が、実際には Input の中では number しか渡さない(更新関数を渡す必要はない)ので、(value: number) => void で良いと思います。

TypeScript

1type InputProps = { 2 currentNum: number; 3 setCurrentNum: (value: number) => void; 4};

Input.spec.tsx はこれで。(props を定義せず、<Input /> の中に直接書いてもいいと思いますけど。)

TypeScript

1 const props = { 2 currentNum: 0, 3 setCurrentNum: (value: number) => {} 4 };

また、setCurrentNum のテストはこんな感じですかね。(いちいち data-testid を設定するのが面倒ですが。)

TypeScript

1 it("setCurrentNum", () => { 2 const mock = jest.fn(); 3 const { getByTestId } = render(<Input currentNum={0} setCurrentNum={mock} />); 4 fireEvent.change(getByTestId('test-input'), { target: { value: '123' } }); 5 fireEvent.click(getByTestId('test-button')); 6 expect(mock).toHaveBeenCalledTimes(1); 7 expect(mock).toHaveBeenCalledWith(123); 8 });

投稿2020/02/15 02:06

hoshi-takanori

総合スコア7895

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問