您好,登錄后才能下訂單哦!
今天給大家介紹一下編寫可測(cè)試的better go代碼示例分析。文章的內(nèi)容小編覺(jué)得不錯(cuò),現(xiàn)在給大家分享一下,覺(jué)得有需要的朋友可以了解一下,希望對(duì)大家有所幫助,下面跟著小編的思路一起來(lái)閱讀吧。
在開(kāi)發(fā)一個(gè)接口的時(shí)候,通常要引入數(shù)據(jù)庫(kù)、redis、或者內(nèi)部調(diào)用其他服務(wù),單元測(cè)試需要先將對(duì)應(yīng)的數(shù)據(jù)庫(kù)、redis、第三方服務(wù)都啟動(dòng),不然,沒(méi)法做單元測(cè)試。 下面就是解決這種情況,原則上認(rèn)為底層相關(guān)服務(wù)都已經(jīng)經(jīng)過(guò)了嚴(yán)格的單元測(cè)試,所以將相關(guān)的方法提取出來(lái),在單元測(cè)試的時(shí)候,模擬替換實(shí)際的數(shù)據(jù)庫(kù)、redis、或其他內(nèi)部的服務(wù)。
下面啟動(dòng)了一個(gè)http服務(wù),對(duì)外提供一個(gè)/bad接口,這個(gè)接口的功能就是接收一個(gè)string類型的參數(shù) args,并通過(guò)db查詢出apps
//better/main.go package main import ( "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.go package service import ( "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 }
數(shù)據(jù)庫(kù)層
//better/dao/apps.go package dao import "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 }
單元測(cè)試代碼
//better/service/bad_test.go package service import ( "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") }
如果要針對(duì)func (h handle) getApps(args string, db *gorm.DB) (apps string, err error) 這個(gè)方法進(jìn)行單元測(cè)試,我們就不得不啟動(dòng)一個(gè)mysql,這樣單元測(cè)試代碼就db嚴(yán)重耦合了。如果方法內(nèi)部還涉及了調(diào)用其他服務(wù),我們還得啟動(dòng)其他服務(wù),這樣單元測(cè)試寫起來(lái)就非常不方便。
新增一個(gè)better接口
//better/main.go package main import ( "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.go package service import "errors" // better go type 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 }
單元測(cè)試
package service import ( "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 { } // 構(gòu)建mock數(shù)據(jù) // 這樣我們就可以測(cè)試我們的方法,而不需要啟動(dòng)一個(gè)db func (m *DBMock) GetApps() (string, error) { return "mock apps", nil }
以上就是編寫可測(cè)試的better go代碼示例分析的全部?jī)?nèi)容了,更多與編寫可測(cè)試的better go代碼示例分析相關(guān)的內(nèi)容可以搜索億速云之前的文章或者瀏覽下面的文章進(jìn)行學(xué)習(xí)哈!相信小編會(huì)給大家增添更多知識(shí),希望大家能夠支持一下億速云!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。