使用 double ( mock objects )

Four-Phase Test 是一種常見的測試 Pattern。幾乎也是一般人在寫測試的手法,依序為:

  • Setup (準備測試資料)
  • Exercie (實際執行測試)
  • Verification (驗證測試結果)
  • Teardown (拆解測試)

但是通常我們在一般寫測試或者是 TDD 時,常常會遇到一些狀況,導致 Setup 階段時,資料「難以被準備」。通常是有以下幾種狀況:

對象物件當中的「協作者」還沒被誕生,比如說都還沒寫到那個 class 或者是 method

對象物件當中的「協作者」是「系統外部物件」,如: API 回傳內容

要準備的資料、相依性過於複雜,要生超多物件才能測試

執行這個測試,呼叫到「吃效能很重」的測試,導致測試運行緩慢

使用替身

但我們的首要要務,其實是要測我們內部的程式的邏輯,不是要測「外部邏輯」的狀況。所以我們可以使用 mock objects,在 RSpec 裡面叫做 double(替身)。

在 Setup 階段使用「替身」的資料,直接進行測試。

舉例來說,我這裡有一個學生計算器

class StudentsCalculator
  def initialize(course)
    @course = course
  end

  def students_count
    @course.students_count
  end
end

我還沒想好 course.students_count 要怎樣設計(這在 TDD 中很常見),但是我知道在 StudentsCalculator 中的邏輯,吃的就是將來 course 提供的 students_count,而且「我現在就想要驗證這件事」。所以我可以假造一個 course 的替身,讓這段測試可以通過。

require "rails_helper"

RSpec.describe StudentsCalculator do
  describe "#students_count" do
    it "returns students count" do
      course = double(:students_count => 5 )
      student_calculator = StudentsCalculator.new(course)
      expect(student_calculator.students_count).to eq(5)
    end
  end
end

results matching ""

    No results matching ""