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()
}
打完收工