iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 6
1
Modern Web

循序漸進學習 Javascript 測試系列 第 6

Day6 理解 Mock 基礎概念:從 Monkey-patching 開始

  • 分享至 

  • xImage
  •  

Mock 是什麼?

單元測試時,假設我們要測試 A 單元,但這個單元需要依賴另一個單元(B 單元),例如:發送一個 request 到 API 。一方面,因為單元測試要盡量隔離需要被測試的單元(A 單元),讓我們純粹測試單元自身內部的功能是否如預期;另一方面,如果每次測試都要發送 request,這樣可能會徒增執行時間跟不必要的開銷,反而讓測試成本變得很大。這時候,我們就需要 Mock 了,簡單來說就是爲依賴的單元(B 單元)做個「替身」,這個替身是可以被決定的,好讓我們可以預期每次的結果。

用 Monkey-patching 來動態更改 Object property

假設我們有個 thumbWar module,接收 player1player2 兩個參數,回傳先贏兩回的 winner 。其中, thumbWar 依賴 utils.getWinner 決定誰是每回的贏家。

thumb-war.js

const utils = require('./utils')

function thumbWar(player1, player2) {
  const numberToWin = 2
  let player1Wins = 0
  let player2Wins = 0
  while (player1Wins < numberToWin && player2Wins < numberToWin) {
    const winner = utils.getWinner(player1, player2)
    if (winner === player1) {
      player1Wins++
    } else if (winner === player2) {
      player2Wins++
    }
  }
  return player1Wins > player2Wins ? player1 : player2
}

module.exports = thumbWar

我們來嘗試將 utils.getWinner mock 起來,確保 thumbWar 的測試結果一致。

現在先建立一個 monkey-patching.js 檔案,呼叫 thumbWar 然後驗證 winner 是 小夫

monkey-patching.js

const assert  = require('assert')
const thumbWar = require('../thumb-war')
const utils = require('../utils')

const winner = thumbWar('小夫', '胖虎')
assert.strictEqual(winner, '小夫')

thumbWar 裡面依賴 utils.getWinner 隨機產生的結果,這個結果不是現在要測試的重點,因此我們將 utils.getWinner 暫時更改為另一個 function,一樣接受兩個參數,但永遠都回傳同一個結果。

monkey-patching.js

utils.getWinner = (p1, p2) => p1

const winner = thumbWar('小夫', '胖虎')
assert.strictEqual(winner, '小夫')

最後,必須將 utils.getWinner 改回原本的 method,才不會影響到其他需要用到 utils.getWinner 的測試:

const originalGetWinner = utils.getWinner // 儲存原本的 method
utils.getWinner = (p1, p2) => p1

const winner = thumbWar('小夫', '胖虎')
assert.strictEqual(winner, '小夫')

utils.getWinner = originalGetWinner // 改回原本的 method

以上這種更改 object property 的方式,通常稱為 monkey patching


上一篇
Day5 靜態分析:讓靜態檢查自動化
下一篇
Day7 理解 Mock 基礎概念:初探 mock function,確保 Functions 被正確呼叫
系列文
循序漸進學習 Javascript 測試30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言