SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

基礎からはじめるReact入門

Reduxにおける同期的/非同期的なAction Creatorをテストする

基礎からはじめるReact入門 第12回

  • X ポスト
  • このエントリーをはてなブックマークに追加

非同期処理をJestでテストする

 本連載で紹介してきたJestの使い方は、どれも同期的な処理をテストするためのものでした。では、非同期処理を伴うテストケースはどのように作成すればよいのでしょうか。同期的なテストと同じ考え方で記述する分には、リスト3のような書き方ができそうです。

[リスト3]これまでと似たような書き方で非同期テストを試みる
describe("doAsync()", () => {
  test("処理結果を確認する", () => {
    doAsync().then(actual => {
      expect(actual).toBe(1);
    })
  });
});

 しかし、この記述ではテストは正しく実施されません。Jestで通常の(同期的な処理をテストするための)スタイルで記述した場合、testに渡した関数の処理が無事に末尾まで実行された時点で、そのテストケースは成功して完了したものと見なされます。完了したテストケースの中でthenが呼ばれても、それはもうテスト結果に寄与することができないのです。

 ですが、ご安心ください。Jestには、非同期処理の結果を検証するための機能がいくつか整備されているので、解説します。具体的には次の4つの記述スタイルのいずれかを選択して使うことになります。

  • コールバックを用いる
  • Promiseを返す
  • resolve/rejectマッチャを用いる
  • async/awaitを用いる

 それぞれの記述スタイルについて、解説します。

コールバックを用いる

 まずは、もっともシンプルな、コールバックを用いるスタイルです。リスト4の通り記述します。

[リスト4]コールバックを用いるスタイルのテストケース
describe("doAsync()", () => {
  test("処理結果を確認する", (done) => { // (1)
    doAsync().then(actual => {
      expect(actual).toBe(1);
      done(); // (2)
    })
  });
});

 リスト3と処理の流れはほとんど同じですが、テストケースの関数が、doneというコールバック関数を引数に取るという違いがあります(1)。この書き方にすると、(2)のようにdone()が実行された場合のみテストが成功したと見なされます。done()が実行されなかった場合は、テストは失敗です。

 今回紹介する他の記述スタイルは、すべてPromiseによる非同期処理を前提としているので、Promiseを用いない非同期処理をテストする場合には、必然的にこのスタイルでテストケースを記述することになります。

Promiseを返す

 次に、Promiseを返すスタイルを紹介します。リスト5のように記述します。

[リスト5]Promiseを返すスタイルのテストケース
describe("doAsync()", () => {
  test("処理結果を確認する", () => {
    expect.assertions(1); // (2)
    return doAsync().then(actual => { // (1)
      expect(actual).toBe(1);
    })
  });
});

 (1)のように、テストケースの関数でPromiseをreturnするのが特徴です。このスタイルにおけるテストケースの成功条件は、次の2つです。

  1. returnしたPromiseが全体としてresolveを返すこと
  2. 所定の回数だけマッチャが実行されること

 2つめの「所定の回数」とは何のことでしょうか。これは(2)のexpect.assertionsで定義した「マッチャを実行する予定の回数」です。今回の例ではtoBeを1回だけ実行しているので、expect.assertions(1)を事前に宣言しました。この回数分だけマッチャが実行されることが、テストケースの成功条件です。

 失敗する条件としては、マッチャの実行回数が足りなかった場合や、Promiseがrejectを返した場合があります。

 また、このスタイルの特殊な用法として、エラーが発生することをテストケースで確認したい場合に適した書き方があります。Promiseの.catch()を使う方法です(リスト6)。

[リスト6]Promiseが失敗することを確認するためのテストケース
describe("doAsync()", () => {
  test("処理が失敗することを確認する", () => {
    expect.assertions(1);
    return doAsync().catch(e => {
      expect(e).not.toBeNull();
    })
  });
});

 .catch()には、catch内部でErrorがthrowされない限りはresolveを返す特性があるので、こういった形での記述も可能になっています。

resolves/rejectsマッチャを用いる

 次に、Promiseを用いた別のスタイルとして、resolvesマッチャやrejectsマッチャを使う方法があります(リスト7)。

[リスト7]resolves/rejectsマッチャを用いるスタイルのテストケース
describe("doAsync()", () => {
  test("処理結果を確認する", () => {
    expect.assertions(1);
    return expect(doAsync()).resolves.toBe(1); // (1)
  });
  test("処理が失敗することを確認する", () => {
    expect.assertions(1);
    return expect(doAsync()).rejects.not.toBeNull(); // (2)
  });
});

 このスタイルの特徴は、expectに非同期処理のPromiseを直接渡す点です(1)。マッチャとして、成功したことを確認したい場合にはresolvesマッチャ、失敗したことを確認したい場合にはrejectsマッチャを続けて記述することによって、Promiseの結果を待つことができます。また、resolvesrejectsの後ろには通常通りのtoBetoEqualといったマッチャをつなげることができます。

async/awaitを用いる

 最後に、async/awaitを用いるスタイルです。リスト8のように記述します。

[リスト8]async/awaitを用いるスタイルのテストケース
describe("doAsync()", () => {
  test("処理結果を確認する", async () => { // (1)
    expect.assertions(1);
    const actual = await doAsync(); // (2)
    expect(actual).toBe(1); // (3)
  });
});

 特徴としては、(1)に示した通り、testに渡す関数にasyncを宣言することです。これにより(2)の通り、テストケースの中でawaitを使えるようになります。この記述スタイルであれば、expectによる検証の部分(3)を同期的な処理のテストケースとまったく同じように書けるので、筆者は好んでこのスタイルを使っています。本記事でも、このスタイルで記述していきます。

次のページ
通信を伴うAction Creatorのテスト

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
基礎からはじめるReact入門連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 中川幸哉(ナカガワユキヤ)

WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/11044 2018/09/07 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング