GitHub
前提条件
配列を仮想DBとした掲示板APIサーバの作成(1/5):はじめに・環境構築・DB、コメントモデルの作成
配列を仮想DBとした掲示板の作成(2/5):GETリクエスト・サーバ起動編
配列を仮想DBとした掲示板の作成(3/5):POSTリクエスト編
配列を仮想DBとした掲示板の作成(4/5):PUTリクエスト編
実装する機能
「DELETE/api/comment/:id」
リクエストを送ると、id値に紐づいたComment1件を削除して、削除したComment1件
がレスポンス値として返ってくる
この記事のまとめ
- 指定したidと合致したcomment1件を削除して、そのコメントを返り値とするメソッドを作成した
- DELETEリクエストを送った時のメソッドを作成した
- メソッド名の変更を行なった
- POSTMANでDELETEリクエスト時の動きを確認した
指定したid値と合致したcomment1件を削除して、削除したコメント1件を返すメソッドの作成(deleteComment()
)
deleteComment: ({ id }) => {
if (typeof id !== 'number' || id < 1) {
throw new Error(
'idに適切でない値が入っています、1以上の数字を入れてください'
);
}
const target = comments.findIndex(comment => id === comment.id);
if (target === -1) {
throw new Error('idと合致するCommentが見つかりません');
}
const deletedComment = comments.splice(target, 1)[0];
return deletedComment;
},
-
id
値に適切でないプロパティ値が入っている -
id
値と合致するcommentが見つからない
上記の場合はエラーを返し、適切な値が入っている場合のみメソッドが成功するように設計しました。
また、idのプロパティ値と配列のインデックス値は同一ではないので、配列内からid値と合致する要素を探す必要があります、そこでArray.prototype.findIndex()
を使用します。
const target = comments.findIndex(comment => id === comment.id);
アロー関数の特徴である、文の戻り値を返すだけならブロックとreturn
を省略した書き方をしています。
これで、id値と合致するコメントを配列内から探すことができます。
そして、コメントを一件削除して、そのコメントを返す必要があります。
const deletedComment = comments.splice(target, 1)[0];
return deletedComment;
Array.prototype.splice()
は破壊的なメソッドです、第一引数に先ほど会得したtarget
、第二引数で削除したい配列の数1
を入れることで、id値と合致するコメント1件がcomments
配列から削除されます。
ここで、splice()
の末尾に[0]
をつけてますが、これをつけることで、配列ではなく1件のデータとして要素を返すことができます。
詳しい説明はこちらで記事にしてます。
【Javascript】splice()の末尾に[0]をつけ取り除かれた要素1つをデータで返す - じんのアウトプット日記(だいたい毎日更新)
それでは、実際にうまく動作するかテストします。
deleteComment()
のテスト
テスト内容
-
Comment.deleteComment
はメソッドである -
id
の引数に不正な値が入っていた場合、エラーが返る -
id
の引数と合致するComment
がない場合、エラーが返る - 適切なデータを送った場合、
id
と合致するComment
1件が返ってくる -
4.
と同時に、id
と合致するComment
1件が配列から削除される。
この5点を確認します。
const assert = require('power-assert');
const Comment = require('../../models/Comment');
describe('Comment.deleteCommentのテスト', () => {
// 以下にテストコードを記述していきます
});
1.Comment.deleteComment
はメソッドである
it('Comment.deleteCommentはメソッドである', () => {
assert.strictEqual(typeof Comment.deleteComment, 'function');
});
typeof
演算子で、Comment.deleteComment
がメソッドであるかどうかテストします。
2.id
の引数に不正な値が入っていた場合、エラーが返る
it('idの引数に不正な値が入っていた場合、エラーが返る', () => {
const invalidIdList = [
{ id: 0 },
{ id: -1 },
{ id: null },
{ id: {} },
{ id: [] },
{ id: '1' },
];
invalidIdList.forEach(id => {
try {
Comment.deleteComment(id);
assert.fail();
} catch (error) {
assert.strictEqual(
error.message,
'idに適切でない値が入っています、1以上の数字を入れてください'
);
}
});
});
invalidIdList
配列に思いつく限りの適切でない値を入れ、forEach
で各値ごとにdeleteComment
を実行します。メソッドがエラーになるようであればcatch
の方でエラーメッセージと比較します。 1つでも成功した場合はassert.fail()
によりエラーで終了、失敗となります。
3.id
の引数と合致するComment
がない場合、エラーが返る
it('idのプロパティ値と合致するCommentがない場合、エラーが返る', () => {
const invalidId = { id: 999999999 };
try {
Comment.deleteComment(invalidId);
assert.fail();
} catch (error) {
assert.strictEqual(error.message, 'idと合致するCommentが見つかりません');
}
});
invalidId
に現在配列には入っていないid値を入れ、deleteComment
を実行します。メソッドがエラーになるようであればcatch
の方でエラーメッセージと比較します。成功した場合はassert.fail()
によりエラーで終了、失敗となります。
4.適切なデータを送った場合、id
と合致するComment
1件が返ってくる
it('適切なid値を送った場合、idと合致するComment一件が返される', () => {
const validId = { id: 1 };
const deletedComment = Comment.deleteComment(validId);
assert.deepEqual(deletedComment, {
id: validId.id,
username: deletedComment.username,
body: deletedComment.body,
createdAt: deletedComment.createdAt,
updatedAt: deletedComment.updatedAt,
});
});
id
に適切な値が入っていた場合は、deleteComment
が実行した時に、返ってくる要素の各プロパティ値には適切にデータが入っているかassert.deepEqual
で確認します。
5.4.
と同時に、id
と合致するComment
1件が配列から削除される。
it('適切なid値を送った場合、idと合致するComment一件が配列から削除される', () => {
const oldComments = Comment.findAll();
const validId = { id: 2 };
Comment.deleteComment(validId);
const currentComments = Comment.findAll();
assert.equal(oldComments.length, currentComments.length + 1);
});
id
に適切な値が入っていた場合は、deleteComment
実行後、配列から要素が一件削除されているかテストします。
各テストが成功したら、次はAPIからDELETE
リクエストをした時に、deleteComment
が実行するようにしていきます。
「DELETE/api/comment/:id」
リクエストを送ると、id値と合致したcomment1件を削除して、削除したcomment1件
がレスポンス値として返ってくるメソッドの作成(deleteComment()
)
deleteComment: (req, res) => {
try {
const parsedId = parseInt(req.params.id, 10);
const removeComment = Comment.removeComment({
id: parsedId
});
res.status(200).json(removeComment);
} catch (error) {
res.status(400).json({ message: error.message });
}
}
router
.route('/:id')
.put(controller.putComment)
.delete(controller.deleteComment);
今回もPUT
リクエストと同じくルートパラメータ
を使用します。ルートパラメータで得た値を数値に変換し、removeComment
のid値に代入します。
と、その前に突然現れたremoveComment
とはなんでしょうか?
メソッド名の変更
今回DELETE
リクエスト時に実行されるdeleteComment
と、指定したid値と合致したComment1件を削除して、削除したコメント1件を返すメソッド
にて、modelsで作成したdeleteComment
の名前が被ってしまいましたので、 modelsの方をremoveComment
と改名しました。
deleteComment()
のテスト
test/app/api
ディレクトリにdeleteComment.test.js
ファイルを新たに作成し、そちらでテストを行なっていきます。
const assert = require('power-assert');
const requestHelper = require('../../../helper/requestHelper');
const getComments = async () => {
const response = await requestHelper.request({
method: 'get',
endPoint: '/api/comments',
statusCode: 200,
});
return response.body;
};
const deleteComment = async (id, code) => {
const response = await requestHelper.request({
method: 'delete',
endPoint: `/api/comments/${id}`,
statusCode: code,
});
return response;
};
describe('TEST 「DELETE api/comments/:id」', () => {
// 以下にテストコードを記述していきます
});
テスト内容
- 適切でない
id
を送ると400
エラーが返る - 送られた
id
とひもづくComment
がない場合、400エラーが返る - 適切なデータを送った場合、
id
とひもづくComment
がレスポンス値として返ってくる。 -
3.
と同時に、配列内にあったidとひもづくComment
は配列から削除される。
この4点を確認するテストコードを記述していきます。
1.適切でないid
を送ると400
エラーが返る
it('適切でないid値を送るとエラーが返る', async () => {
const response = await deleteComment(0, 400);
assert.deepStrictEqual(response.body, {
message: 'idに適切でない値が入っています、1以上の数字を入れてください',
});
});
id値に0(適切でない数値)を入れると、ステータスコードは400
、そしてエラーメッセージが返ってくることを確認します。
2.送られたid
とひもづくComment
がない場合、400エラーが返る
it('idの値と合致するCommentがない場合エラーが返る', async () => {
const response = await deleteComment(9999999, 400);
assert.deepStrictEqual(response.body, {
message: 'idと合致するCommentが見つかりません',
});
});
現在配列に入っているcommentのidのどれにも合致しない数字をidに入れると、ステータスコードは400
、そしてエラーメッセージが返ってくることを確認します。
3.適切なデータを送った場合、id
とひもづくcomment
1件がレスポンス値として返ってくる。
4.3.
と同時に、配列内にあったidとひもづくcomment
1件は配列comments
から削除される。
it('適切なid値を送ると、idと合致するCommentが返ってくる、また該当のCommentは配列内から削除される', async () => {
const oldComments = await getComments();
const validId = 4;
const response = await deleteComment(validId, 200);
const comment = response.body;
assert.deepStrictEqual(comment, {
id: validId,
username: comment.username,
body: comment.body,
createdAt: comment.createdAt,
updatedAt: comment.updatedAt,
});
const currentComments = await getComments();
assert.strictEqual(oldComments.length, currentComments.length + 1);
});
id値と合致するcommentがあった場合、合致したcomment1件、ステータスコード200
が適切に返ってきていることを確認します。
それと同時に、deleteComment
実行前と実行後の配列を比較して、comment1件が削除されていることを確認します。
以上のテストが全て正常に終了したら、今回のAPIサーバを用いた掲示板の作成
は全て終了です。
最終的な環境
.
├── Task_info.md
├── app.js
├── controllers
│ └── comments.js
├── helper
│ └── requestHelper.js
├── index.js
├── models
│ └── Comment.js
├── package-lock.json
├── package.json
├── readme.md
├── routers
│ └── comments.js
└── test
├── app
│ └── api
│ ├── deleteComment.test.js
│ ├── getComment.test.js
│ ├── postComment.test.js
│ └── putComment.test.js
├── mocha.opts
└── models
├── createComment.test.js
├── findAll.test.js
├── removeComment.test.js
└── updateComment.test.js