Test-Driven Development - Go (4)
go golang TDD Test-Driven Development Dependency Injection
看完前面的篇章
或許會覺得 測試就是這麼簡單啊
但是當你嘗試在專案裡面這樣使用的時候
會發現有許多問題要處理,好像沒有那麼簡單
以下面的 Code 為例, function 裡面用到了外部的 db
因為實際的 Database 的回應是不可控的
就無法保證每次的測試結果都會相同
  var db *gorm.DB
  func GetUserCount() (count int, err error) {
    err = db. // 這裡就用到了外部的 db, 測試時的不確定因數
        Table("customers").
        Count(&count).
        Error
    return
  }
解決這種不確定因數的方式,就是把 db 變成從外部傳入
這種手法就叫做 Dependency Injection(依賴性注入)
修改後的 Code
  func GetUserCount(db *gorm.DB) (count int, err error) {
    err = db. // 這時候 db 就是從外部傳進來,是可控的
        Table("customers").
        Count(&count).
        Error
    return
  }
另外一個問題是,就算是外部傳入,有時候也是很難控制
比如我們剛才在說的 Database,很難在測試的時候給出一個 Mock 的 Database
所以就要把 function 的輸入參數變成一個 Interface
就會更容易去 Mock
  // 現有程式碼
  type db struct {
    gorm.DB
  }
  func (d *db) Count() (count int, err error) {
    err = d.
      Table("customers").
      Count(&count).
      Error
    return
  }
  // 未使用 Mock 的 function
  func GetCount(d *db) (count int, err error) {
    return d.Count()
  }
  // Mock 的 interface
  type DataStore interface {
    Count() (count int, err error)
  }
  // 使用 Mock 的 function
  func GetCount(d DataStore) (count int, err error) {
    return d.Count()
  }
打完收工