# 2020年10月10日モブプロ#8
[MDの書き方](https://qiita.com/tbpgr/items/989c6badefff69377da7)
モブプロのコンテンツは🤟がついています。
# 本日の目標
ひたすらテストコードを書いていく!
# Jestの参考サイト
- [Facebook製のJavaScriptテストツール「Jest」の逆引き使用例 - Qiita](https://qiita.com/chimame/items/e97883fd46b67529d59f)
- [Getting Started - Jest](https://jestjs.io/docs/ja/getting-started)
# テストコードを書いていこう🤟
- エンドポイントのテストはJestはできないので以下を使用する
- https://www.npmjs.com/package/supertest
## テストの分類分け
describeを使って、ファイル単位、メソッド単位にテストを分けて書いていく
```javascript=
describe('routers/tasks.js', () => {
describe('get method', () => {
})
})
```
## GETメソッドのテストコードを書く
### Task全取得
```javascript=
describe('get method', () => {
it('response', async () => {
const response = await request(app).get('/tasks')
expect(response.statusCode).toBe(200)
})
})
```
いい感じ。
```shell=
> jest
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.415 s
```
でも、なにかエラーが表示される。
```shell=
● Cannot log after tests are done. Did you forget to wait for something async in your test?
Attempted to log "Executing (default): ALTER TABLE `Tasks` CHANGE `title` `title` VARCHAR(255) NOT NULL;".
at CustomConsole.log (node_modules/@jest/console/build/CustomConsole.js:185:10)
at Sequelize.log (node_modules/sequelize/lib/sequelize.js:1171:15)
at Query._logQuery (node_modules/sequelize/lib/dialects/abstract/query.js:352:22)
at Query.run (node_modules/sequelize/lib/dialects/mysql/query.js:36:27)
at node_modules/sequelize/lib/sequelize.js:619:28
at Function.sync (node_modules/sequelize/lib/model.js:1349:11)
```
APIサーバ起動時にコンソールログが出力されるが、そのログに対してテストしなくて大丈夫かどうかを尋ねるメッセージの模様。
本来は、ちゃんとテストするか、出力されないようにするなどの対応をするべきだが、一旦以下のオプションで無視する。
```shell=
jest --silent
```
### レスポンスが配列かどうかのテスト
```javascript=
expect(Array.isArray(response.body)).toBe(true) // => passed!
```
上記を先程の`expect()`の下に追加。
`tobe(true)`は`toBeTruthy()`に置き換えることができる。
```javascript=
expect(Array.isArray(response.body)).toBeTruthy() // => passed!
```
### ID指定での取得テスト
```javascript=
it('response with id', async () =>{
const response = await request(app).get('/tasks/13')
expect(response.statusCode).toBe(200)
// IDはNumber型?
expect(Number.isInteger(response.body.id)).toBeTruthy()
// titleは合ってる?
expect(response.body.title).toBe('test1')
// doneはfalseかな?
expect(response.body.done).toBeFalsy()
})
```
### 存在しないIDのエラーテスト
```javascript=
// id = 12は存在しないはず...
it('response with unknown id', async () =>{
const response = await request(app).get('/tasks/12')
expect(response.statusCode).toBe(404)
})
```
## テストデータの追加
上記の書き方と汎用性がないのでテストデータを追加する。
```javascript=
const Task = require('../src/models/tasks')
// テストデータを新規追加
const task = await Task.create({title:'test'})
const id = task.id
```
## POSTメソッドのテストコードを書いていく
```javascript=
describe('post method', () => {
it('response with data', async () => {
const data = {title: "test"}
const response = await request(app).post('/tasks').send(data)
expect(response.statusCode).toBe(201)
})
})
```
### 失敗するようにしてみる
```javascript=
it('response without data', async () => {
const response = await request(app).post('/tasks')
expect(response.statusCode).toBe(400)
})
```
エラーで落ちちゃう。
エラー処理を書いてなかった!
```javascript=
// routers/tasks.js
router.post('/tasks', async (req, res) => {
const title = req.body.title
try {
const task = await Task.create({
title
})
res.status(201).send(task)
} catch(e) {
res.status(400).send()
}
})
```
エラー処理を追加してあげる。
## DELETEメソッドのテストコードを書いていく
```javascript=
describe('delete method', () => {
it('response with id', async () => {
const task = await Task.create({title:'test'})
const id = task.id
const response = await request(app).delete(`/tasks/${id}`)
// 削除完了している?
expect(response.statusCode).toBe(200)
// 中身消えてる?
expect(response.body.id).toBeUndefined()
})
// 存在しないIDで404が返ってくるか
it('response with unknown id', async () => {
const id = 0
const response = await request(app).delete(`/tasks/${id}`)
expect(response.statusCode).toBe(404)
})
})
```
## PATCHメソッドのテストコードを書いていく
```javascript=
describe('patch method', () => {
it('response with id and data', async () => {
const task = await Task.create({title:'test'})
const id = task.id
const data = { title:"test2",done:true}
const response = await request(app).patch(`/tasks/${id}`).send(data)
// 成功した?
expect(response.statusCode).toBe(200)
expect(response.body.id).toBe(id)
expect(response.body.done).toBeTruthy()
expect(response.body.title).toBe(data.title)
})
})
```
### IDがなかった場合の処理
```javascript=
it('respose with unknown id', async ()=> {
const id = 0
const data = { title:"test2",done:true}
const response = await request(app).patch(`/tasks/${id}`).send(data)
expect(response.statusCode).toBe(404)
})
```
## テストコード記述時の注意💥
### **テストコードは共通化しない!**
どこで失敗したかわからなくなるため共通化はご法度。
コピペで記述しましょう。