どうも、つよぽんです!
今回は「APIサーバーを実装するシリーズ」の第5回目の記事となります。
以前、Modelを作成した時の記事「【APIサーバー】データ一覧取得する機能の追加【Model実装】」をまだ読んでいない方は、先にそちらの記事から読むことをオススメします。
第5回目の今回は、以前作成したModelに「データ1件を新規作成する機能」の実装を行います。
今回の記事内容は、以下のリンク先で使っているスライドの一部を補足した記事になります。
実際に手を動かしながら覚えたい方は、以下のスライドも参考にすると良いでしょう。
今回の記事は次のような方に向けて書きました。
- Modelに機能を追加実装する流れを理解したい方
- Modelに追加実装した機能のテストコードを追加したい方
この記事を読み終えた後のあなたは次のことがわかるようになっています。
- Modelに機能を追加実装できるようになる
- Modelに追加実装した機能のテストコードを書けるようになる
それでは以下の内容で話を進めていきます。
- Modelのデータ一覧取得メソッド「findAll」を修正する
- Modelにデータ1件を新規作成するメソッド「create」を実装する
- データ1件を新規作成する機能のテストコードを作成する
目次
Modelのデータ一覧取得メソッド「findAll」を修正する
以前の書いた記事「【APIサーバー】データ一覧取得する機能の追加【Model実装】」でデータ一覧取得の機能として「findAll」メソッドをModelに実装しました。
しかし、前回実装したfindAllメソッドには問題があります。
以下の画像の左側が前回実装したfindAllメソッド、右側が今回の修正後のfindAllメソッドとなります。(※画像をクリックする別タブで画像が開きます)
違いが何かわかるでしょうか?
結論から言うと以下のとおりです。
- 前回実装したfindAllメソッド(画像の左側のコード)は、配列の参照を返している
- 今回修正したfindAllメソッド(画像の右側のコード)は、配列のコピーを返している
参照の挙動に関しては、以前書いた記事「JavaScriptの参照に注意【オブジェクト型の特有な動き】」に書いてあるので詳しくはそちらを参考にしていただけたらと思います。
後ほど、テスト実装の際にも説明しますが、参照を返すようにすると、findAllメソッドで取得した値が勝手に更新されてしまうので、勝手な更新を防ぐために「配列のコピー」を返すようにしました。
Modelにデータ1件を新規作成するメソッド「create」を実装する
createメソッドの全体像
以下の画像の右側にある赤枠で囲った部分が、今回実装する「createメソッド」の全体像となります。(※画像をクリックする別タブで画像が開きます)
ModelのfindAllメソッドの下の方に、上のコードを追加していただけたらと思います。
それでは、createメソッド内で実装している内容を1つずつ説明していきます。
createメソッドの引数
以下の画像の赤枠で囲った部分を見るとわかる通り、createメソッドは引数に1つのオブジェクトを受け取り、プロパティに「title」「body」を持ちます。(※画像をクリックする別タブで画像が開きます)
つまり、Model(=Todo.js)のcreateメソッドを実行するときは以下のように実装します。
1 2 3 4 |
Todo.create({ title: 'Todoのタイトル', body: 'Todoの説明文' }); |
必要なデータが無かったらエラーを投げる
以下の画像の赤枠で囲った部分では、引数で受け取る「title」「body」に値が入っていない場合、エラーを投げて処理を中断しています。(※画像をクリックする別タブで画像が開きます)
処理を中断することによって、不正なデータが、ダミーのDB(今回は配列)に含まれるのを防ぐことができます。
引数で受け取ったtitle, bodyを元にデータ1件を新規作成する
以下の画像の赤枠で囲った部分では、引数で受け取った「title」「body」を使って「新しいTodo1件を作成して、ダミーのDB(=配列)に保存」を行っています。(※画像をクリックする別タブで画像が開きます)
作成したデータを呼び出し元に返す
以下の画像の赤枠で囲った部分では、「新しく作成したTodoを呼び出し元に返す」ことを行っています。(※画像をクリックする別タブで画像が開きます)
データ1件を新規作成する機能のテストコードを作成する
テストファイルの作成
以下の画像の赤枠で囲った部分では、今回実装した「create」メソッドに対応するファイルとして「create.test.js」を「test/models/Todo」ディレクトリ内に作成します。(※画像をクリックする別タブで画像が開きます)
Todo.createがメソッドであることをテストする
以下の画像の赤枠で囲った部分は、「Todo.create」がメソッドであるかどうかをテストするコードです。(※画像をクリックする別タブで画像が開きます)
titleプロパティに値がない時にエラーになることをテストする
以下の画像の赤枠で囲った部分は、「Todo.create」メソッド実行時、「title」プロパティに値がないときにエラーになることをテストしているコードです。(※画像をクリックする別タブで画像が開きます)
bodyプロパティに値がない時にエラーになることをテストする
以下の画像は、「Todo.create」メソッド実行時、「body」プロパティに値がないときにエラーになることをテストしているコードです。(※画像をクリックする別タブで画像が開きます)
createメソッドの戻り値の確認と、craeteメソッド実行前後でデータが1件増えていることをテストする
以下の画像の赤枠で囲った部分は、「Todo.create」メソッド実行して成功した時のテストコードです。(※画像をクリックする別タブで画像が開きます)
この記事の最初のほうで、findAllメソッドを修正したことを覚えてますでしょうか?
修正前はデータ一覧を保存している「配列の参照」を返していて、修正後は「配列のコピー」を返すようにしました。
もし、配列の参照を返すようにしていたら、このテストは失敗します。
理由は、1つ目の赤枠にかかれている「oldTodos」と、2つ目の赤枠の「currrentTodos」は同じ参照値を持った配列となります。
つまり、currentTodosの配列を変更すると、oldTodosもcurrentTodosと同じように配列に変更が入り、常に「oldTodosの中身とcurrentTodosの中身」が同じ状態になります。
しかし、実際には、oldTodosとcurrentTodosはそれぞれ独立した配列が望ましいです。
例えば、データを1件追加する前の状態を保存しておきたい場合に、同じ参照を持っていると、データを1件追加する前の状態を保持できません。
そのため、findAllメソッドを修正して、配列の参照ではなくコピーを返すようにしました。
配列の参照とコピーの挙動の違いに関しては以下の記事をまとめているので、そちらを参考にしていただけたらと思います。
実装したテストが成功するか確認する
以下の画像は、これまで実装してきた「create」メソッドのテストコードを実行したようすになります。(※画像をクリックする別タブで画像が開きます)
下の赤枠のように全てのテストが通ることが確認できたら、createメソッドの実装と、createメソッドのテストコードの実装は完了となります。
まとめ
今回の話をまとめると次のとおりです。
- findAllメソッドを修正して、配列の参照はなく、コピーを返すようにした
- Modelにcreateメソッドを追加実装した
- Modelに追加実装したcreateメソッドのテストコードを実装した
今回の内容は以下の記事内のスライドでも学習できます。