iT邦幫忙

2021 iThome 鐵人賽

DAY 17
0
Modern Web

Let's Go! 解剖Go server開發到部署的過程系列 第 17

day 17 - 利用 interface 來mock外部回應

到目前為止所跑的測試都是利用 docker 在本機run scylla & redis 測試的,
今天利用Go interface 來把model的程式改成不需要依賴外部回應的方式。

Go有兩種interface, 一個是資料型別, 一個是定義接口。

  • 資料型別的interface 會像這樣使用:

      // 宣告參數 interface{}
     var data interface{}
     // 傳入參數 interface{}
      func Test(i interface{}) (r string) {}
      // 回傳參數 interface{}
     func Test(i string) (r interface{}) {}
    ``
    就跟`int`, `string`, `bool`一樣, 用來表示資料的型態。
    
    
  • 定義接口的interface 會是這樣使用:

    ype ITest interface{
        Create(seq int, data string) error
        Update(t *Test) error
    
    ``
    在Go裡面只要有一個 struct 滿足 `Create()` 和 `Update()`兩個接口條件, 
    就可以透過將變數宣告為 ITest 來調用不同struct底下的接口。
    這個特性可以用在本機測試, 如果已知對接的接口或API回應格式, 就可以實作mock的API接口來測試。
    
    
    
  • 修改model底下的程式, 調整為interface接口

    model
    ├── init.go
    └── limit.go
    
  • 實作內容

    package coconut_model
    
    import (
        "github.com/syhlion/gocql"
    )
    
    // Init 
    func Init(cql *gocql.Session) {
        LimitSQL = &RealModel{
            cqlDB: cql,
        }
    }
    
    // InitMock 
    func InitMock() {
        LimitSQL = &MockModel{}
    }
    
    type IModel interface {
        GetLimit() (result map[string]int, err error)
    }
    
    var LimitSQL IModel
    
    type RealModel struct {
        cqlDB *gocql.Session
    }
    
    func (r *RealModel) GetLimit() (result map[string]int, err error) {
        var (
            level string
            limit int
        )
    
        result = make(map[string]int)
    
        sql := `select level, limit_point from coconut.settings`
        iter := r.cqlDB.Query(sql).Iter()
    
        for iter.Scan(&level, &limit) {
            result[level] = limit
        }
    
        if err := iter.Close(); err != nil {
            return nil, err
        }
    
        return
    }
    
    type MockModel struct{}
    
    func (m *MockModel) GetLimit() (result map[string]int, err error) {
        result = make(map[string]int, 0)
        result["0"] = 11111
        result["1"] = 2222
        result["2"] = 333
        result["3"] = 55
    
        return result, nil
    }
    
    
  • 在config中加入一個參數config.Environment 決定要不要跑mock的環境

        if config.Environment == "local" {
            coconut_model.InitMock()
        } else {
            coconut_model.Init(session)
        }
    
  • 調整 rpc.go

        limitSettings, err := coconut_model.LimitSQL.GetLimit()
    

Mock 在以前使用 Http API的時候比較能明顯感受到它的便利性, 只要API格式確認之後就可以Mock出來開發,後來使用gRPC服務之後就有spec可以參考了, 所以目前比較常用來Mock的是對資料庫或redis取資料的回應狀況。


上一篇
day 16 - 開啟git worktree 進行redis lua-script 測試比較
下一篇
day 18 - graceful shutdown 優雅地退場
系列文
Let's Go! 解剖Go server開發到部署的過程30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言