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 会是这样使用:

      type 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 20:专案04 - Facebook爬虫01 | ChromeDriver、Selenium

>>:  Kotlin 语言

Day 30 QuickSight 功能介绍

在资料源设定完成後,接下来介绍如何绘制图表 资料源是代表着每个 User 购买数量前五多的商品,而这...

结语

前言 今年13th铁人终於来到了尾声,又过了一年时间过得很快,今年是第二年的挑战(依旧主管迫害啊~)...

Day 13:AWS是什麽?30天从动漫/影视作品看AWS服务应用 -《JoJo的奇妙冒险》第三季 part 3

延续上一篇的「穿心攻击」概念,其所应用的机器学习原理是所谓的「强化学习」(Reinforcement...

Alpine Linux Porting (1.11?)

进场大修的一天,拿了包高血压药。在候诊间持续debug人生XD 依旧先上个进度图: + mkdir ...

Chapter3 - canvas动画续篇 加入Z轴也能使2D画面产生立体的空间感

https://jerry-the-potato.github.io/ChapterX-demo/ ...