网创优客建站品牌官网
为成都网站建设公司企业提供高品质网站建设
热线:028-86922220
成都专业网站建设公司

定制建站费用3500元

符合中小企业对网站设计、功能常规化式的企业展示型网站建设

成都品牌网站建设

品牌网站建设费用6000元

本套餐主要针对企业品牌型网站、中高端设计、前端互动体验...

成都商城网站建设

商城网站建设费用8000元

商城网站建设因基本功能的需求不同费用上面也有很大的差别...

成都微信网站建设

手机微信网站建站3000元

手机微信网站开发、微信官网、微信商城网站...

建站知识

当前位置:首页 > 建站知识

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

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

创新互联公司基于分布式IDC数据中心构建的平台为众多户提供西部信息服务器托管 四川大带宽租用 成都机柜租用 成都服务器租用。

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

一个普通的例子

下面启动了一个http服务,对外提供一个/bad接口,这个接口的功能就是接收一个string类型的参数 args,并通过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
}

数据库层

//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
}

单元测试代码

//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")
}

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

一种更好的实现方式

新增一个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
}

单元测试

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 {
}

// 构建mock数据
// 这样我们就可以测试我们的方法,而不需要启动一个db
func (m *DBMock) GetApps() (string, error) {
    return "mock apps", nil
}

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


新闻名称:编写可测试的bettergo代码示例分析
网页网址:http://bjjierui.cn/article/jgjgsc.html

其他资讯