測試你的 React App 使用 Mock Server

tags: React Testing
category: Front-End
description: 測試你的 React App 使用 Mock Server
created_at: 2022/01/15 14:00:00

cover image


事前準備

  • 裝好 Node.js

前言

繼上篇測試之後,這次希望整合 API 做測試,但是有時候又不能去打真的 API , 那就只能做一個模擬(Mock)的了。


實作範例

這次做的範例比上次更簡單,我要一個按鈕,點下去之後跟 API 要資料顯示在畫面上


先做一個真實的 API

這邊使用 express 當範例

先建立專案

npm init -y

再來安裝套件

npm i express cors

再來建立 app.js

const express = require('express')
const cors = require('cors')
const app = express()
const port = 8000

app.use(cors())
app.get('/hello', (req, res) => {
  res.send('Hello World.')
})

app.listen(port, () => {
  console.log(`Listening at http://localhost:${port}`)
})

這樣去跑 node app.js 會看到 API 已經啟動,可以輸入 http://localhost:8000/hello 存取


做前端

import React, { useState } from 'react'

function App() {
  const [response, setResponse] = useState(null)

  const getResponse = () => {
    fetch('http://localhost:8000/hello')
      .then((res) => res.text())
      .then((data) => {
        setResponse(data)
      })
  }

  return (
    <div className="App">
      <span data-testid="response-span">{response}</span>
      <button onClick={getResponse}>Get Response</button>
    </div>
  )
}

export default App

再來啟動 Server 應該可以看到一個按鈕,點下去之後會去向 API 請求,得到回應後會渲染在畫面上。


寫測試

import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import React from 'react'
import App from './App'

test('get response button function', async () => {
  render(<App />)
  const buttonElement = screen.getByRole('button', { name: 'Get Response' })
  fireEvent.click(buttonElement)

  const spanElement = screen.getByTestId('response-span')
  await waitFor(() => expect(spanElement.textContent).toBe('Hello World.'))
})

然後跑測試,會發現 PASS,但是這樣實際去向 API 發了請求,如果我們 API 有對資料庫做操作或一些不可逆的操作將會引來災難,所以我們需要一個模擬(Mock)API


使用 Mock Service Worker

安裝

$ npm install msw --save-dev
# or
$ yarn add msw --dev

建立 src/mocks/handlers.js

import { rest } from 'msw'

export const handlers = [
  rest.get(`http://localhost:8000/hello`, (req, res, ctx) => {
    return res(ctx.status(200), ctx.text('Hello World.'))
  }),
]

再來到 src/setupTests.js 加上相關設定

// ...
import { handlers } from 'mocks/handlers'
import { setupServer } from 'msw/node'

const server = setupServer(...handlers)
beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())

再來跑測試會看到類似下面這樣

PASS  src/App.test.js
  √ get response button function (100 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.191 s
Ran all test suites.

這樣就完成了,如果你要確認的話可以在 APILog 或是故意把 Mock API 回傳的資料改變,讓他失敗。




最後更新時間: 2022年01月15日.