千家信息网

编写可测试的better go代码示例分析

发表于:2025-01-31 作者:千家信息网编辑
千家信息网最后更新 2025年01月31日,今天给大家介绍一下编写可测试的better go代码示例分析。文章的内容小编觉得不错,现在给大家分享一下,觉得有需要的朋友可以了解一下,希望对大家有所帮助,下面跟着小编的思路一起来阅读吧。在开发一个接
千家信息网最后更新 2025年01月31日编写可测试的better go代码示例分析

今天给大家介绍一下编写可测试的better go代码示例分析。文章的内容小编觉得不错,现在给大家分享一下,觉得有需要的朋友可以了解一下,希望对大家有所帮助,下面跟着小编的思路一起来阅读吧。

在开发一个接口的时候,通常要引入数据库、redis、或者内部调用其他服务,单元测试需要先将对应的数据库、redis、第三方服务都启动,不然,没法做单元测试。 下面就是解决这种情况,原则上认为底层相关服务都已经经过了严格的单元测试,所以将相关的方法提取出来,在单元测试的时候,模拟替换实际的数据库、redis、或其他内部的服务。

一个普通的例子

下面启动了一个http服务,对外提供一个/bad接口,这个接口的功能就是接收一个string类型的参数 args,并通过db查询出apps

//better/main.gopackage mainimport (    "errors"    "net/http"    "better/service"    "github.com/jinzhu/gorm")func main() {    http.HandleFunc("/bad", func(w http.ResponseWriter, r *http.Request) {        args := r.URL.Query().Get("args")        //init db        db, err := dao.NewStorage()        if err != nil {            w.Write([]byte(err.Error()))            w.WriteHeader(http.StatusBadRequest)            return        }        apps, err := service.NewHandle().GetApps(args, db.DB)        if err != nil {            w.Write([]byte(err.Error()))            w.WriteHeader(http.StatusBadRequest)            return        }        w.Write([]byte(apps))        w.WriteHeader(http.StatusOK)        return    })    err := http.ListenAndServe(":8080", nil)    if err != nil {        panic(err)    }}

service层

//better/service/bad.gopackage serviceimport (    "errors"    "github.com/jinzhu/gorm")type handle struct {}func NewHandle() *handle {    return &handle{}}func (h handle) GetApps(args string, db *gorm.DB) (apps string, err error) {    if args == "" {        return "", errors.New("args is nil")    }    //引入 db    err = db.Find(&apps).Error    if err != nil {        return "", err    }    return apps, nil}

数据库层

//better/dao/apps.gopackage daoimport "github.com/jinzhu/gorm"type Storage struct {    DB *gorm.DB}func NewStorage() (*Storage, error) {    db, err := gorm.Open("user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local")    if err != nil {        return nil, err    }    return &Storage{DB: db}, nil}func (s *Storage) GetApps() (string, error) {    return "dao apps", nil}

单元测试代码

//better/service/bad_test.gopackage serviceimport (    "testing"    "github.com/jinzhu/gorm")func Test_GetApps(t *testing.T) {    db, err := gorm.Open("user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local")    if err != nil {        t.Fatal("gorm open err", err.Error())    }    _, err = NewHandle().GetApps("test", db)    if err != nil {        t.Fatal("getApps err", err.Error())    }    t.Log("success")}

如果要针对func (h handle) getApps(args string, db *gorm.DB) (apps string, err error) 这个方法进行单元测试,我们就不得不启动一个mysql,这样单元测试代码就db严重耦合了。如果方法内部还涉及了调用其他服务,我们还得启动其他服务,这样单元测试写起来就非常不方便。

一种更好的实现方式

新增一个better接口

//better/main.gopackage mainimport (    "net/http"    "better/dao"    "better/service"    "github.com/jinzhu/gorm")func main() {    http.HandleFunc("/better", func(w http.ResponseWriter, r *http.Request) {        args := r.URL.Query().Get("args")        //init db        db, err := dao.NewStorage()        if err != nil {            w.Write([]byte(err.Error()))            w.WriteHeader(http.StatusBadRequest)            return        }        apps, err := service.NewBetterHandle(db).GetApps(args)        if err != nil {            w.Write([]byte(err.Error()))            w.WriteHeader(http.StatusBadRequest)            return        }        w.Write([]byte(apps))        w.WriteHeader(http.StatusOK)        return    })    err := http.ListenAndServe(":8080", nil)    if err != nil {        panic(err)    }}

service层

//better/service/better.gopackage serviceimport "errors"// better gotype betterHandle struct {    Storage BetterHandleStorage}type BetterHandleStorage interface {    GetApps() (string, error)}func NewBetterHandle(storage BetterHandleStorage) *betterHandle {    return &betterHandle{Storage: storage}}func (h betterHandle) GetApps(args string) (apps string, err error) {    if args == "" {        return "", errors.New("args is nil")    }    apps, err = h.Storage.GetApps()    if err != nil {        return "", err    }    return apps, nil}

单元测试

package serviceimport (    "testing")func Test_BetterGetApps(t *testing.T) {    var m DBMock    apps, err := NewBetterHandle(&m).GetApps("Test_BetterGetApps")    if err != nil {        t.Fatal("getApps err", err.Error())    }    t.Log("apps:", apps)}type DBMock struct {}// 构建mock数据// 这样我们就可以测试我们的方法,而不需要启动一个dbfunc (m *DBMock) GetApps() (string, error) {    return "mock apps", nil}

以上就是编写可测试的better go代码示例分析的全部内容了,更多与编写可测试的better go代码示例分析相关的内容可以搜索之前的文章或者浏览下面的文章进行学习哈!相信小编会给大家增添更多知识,希望大家能够支持一下!

0