私は React と Jest を初めて使用するため、これまでのところほとんどすべてのことに苦労しています。見つけたチュートリアルに従おうとしています。
これは、シンプルなブックストア React フロントエンド アプリケーションです。ここまでは、単純なレイアウト コンポーネントを作成し、次に取得した本のリストを含む BookContainer コンポーネント内に BookList コンポーネントを作成しました。次に、各書籍には BookListItem コンポーネントがあります。
次に、バックエンドの Rest API から書籍を取得するための単純な BookService と getAllBooks を用意します。さらに、Redux ストアへの保存とそこからの取得をすべて処理する単純な BookReducer、BookSelector、BookAction があります。
redux、react-hooks、redux ツールキット、jest、JavaScript を使用しています。
これを Web ブラウザで実行すると、すべてが正常に動作し、書籍が取得されてストアに保存され、BookContainer コンポーネントでレンダリングされます。
今、この BookContainer コンポーネントに簡単な単体テストを追加しようとしており、ヘルプを探しています。
この単体テストでは、BookList コンポーネントがレンダリングされたかどうか (haveBeenCalledWith)、つまり render メソッドに渡した書籍のリストをチェックしたいと考えています。
また、レンダリングに渡す書籍のリストを返す BookAction をモックしたいと考えています。まさにこれが私が今取り組んでいることです。
これは私の BookContainer コンポーネントです:
リーリーこれは私の BookList コンポーネントです:
リーリーこれは私の BookAction です:
リーリーこれは私の BookContainer.test.jsx です:
リーリーこれは、テストで使用する bookContainerStateWithData の TestDataProvider です:
リーリーこれは、テストで使用する TestSetupProvider の renderWithRedux() ヘルパー メソッドです:
リーリーこれは、TestSetupProvider で使用される createSoteWithMiddleware() を提供する私の ReduxStoreHelper です:
リーリーおよび現在受信しているエラー メッセージ:
リーリーBookContainer 単体テストのこの行:
リーリー助けやアドバイスをありがとうございます。同様の問題と解決策を探してきましたが、これまでのところ成功していません。
getBooksAction のジョーク モックに __esModule: true
を次のように追加すると:
その場合、エラー メッセージは異なります:
リーリーgetBooksAction キーを次のようにジョーク シミュレーションのデフォルトに変更すると:
リーリーこの場合、型エラーはなくなりましたが、アサーション エラーが発生しました (もう少し近いものになります):
リーリーしたがって、空の書籍配列が返されるようになりました。では、与えられた書籍の配列を発送するようにシミュレーションを変更するにはどうすればよいでしょうか?
問題の根本原因が見つかったと思います。 BookContainer が作成されてレンダリングされると、書籍が連続して複数回フェッチされます。最初の 2 つは空の書籍配列を返します。 3回目以降は取得したbooks配列を返却します。これは、 useEffect の後に BookContainer にコンソール ログを追加することでわかります:
リーリー連続で何度も呼び出す必要がありますか?書籍の配列を正しく取得するには、1 回の呼び出しだけでよいのではないでしょうか?この動作の原因は何ですか。コードのどこかに問題があるのでしょうか?
ちなみに、これが BookContainer コンポーネントにこの迷惑な IF ステートメントがある理由でもあります。チュートリアルには記載されていませんが、すべてが期待どおりに機能します。 BookContainer がレンダリングされるたびに、リクエスト/操作が 2 倍になるようです...
インデックス ファイルで StrictMode を使用しました。これを削除した後、二重リクエストはなくなり、BookContainer の useEffect() は 1 回だけ実行されるようになりました。ただし、BookContainer の render メソッドは依然として 2 回実行されます。1 回目は空のブック配列で、2 回目はフェッチされたブック配列で実行されます。
P粉9860280392024-02-27 00:23:34
最終的な根本原因は、バックエンドとフロントエンドの間の応答データのマッピングが間違っていたことでした。
get book エンドポイントに対する私の API 応答は次のとおりです:
{ 「本」: [...] }
つまり、基本的には json 配列ではなく、内部に配列を含む json オブジェクトです。 API 応答の優れた実践例にあるように、より柔軟になる必要があります。
ただし、私のフロントエンドでは、私が書いたコードは基本的に、API 応答が BookList 内の単なる json 配列であると誤って想定しています。
const propTypes = { 本: Proptypes.arrayOf( Proptypes.shape({ id: Proptypes.number.isRequired、 タイトル: Proptypes.string.isRequired、 説明: Proptypes.string.isRequired、 著者: Proptypes.string.isRequired、 release Year: Proptypes.number.isRequired、 }) )。が必要です、 };次のように変更します:
const propTypes = { BooksResponse: Proptypes.shape({ 本: Proptypes.arrayOf( Proptypes.shape({ id: Proptypes.number.isRequired、 タイトル: Proptypes.string.isRequired、 説明: Proptypes.string.isRequired、 著者: Proptypes.string.isRequired、 release Year: Proptypes.number.isRequired、 }) )。が必要です、 }) };
次に、この変更を BookList コンポーネントにさらに適用します:
const BookList = ({booksResponse}) => { 戻る ( <ボックスクラス名={styles.bookList} ml={5}> {booksResponse.books.map((本) => { 戻る ( <BookListItem book={book} key={book.id} /> ); })} </ボックス> ); }
最後に単体テストでも:
expect(BookList).toHaveBeenLastCalledWith({booksResponse:books }, {});
そして、getBooksAction モックにはデフォルトや __esModule は必要ありません:
jest.mock("../../../modules/book/BookAction", () => ({ getBooksAction: jest.fn()、 }));
すべてが期待どおりに機能します。 :)