Unit testing 如何为另一个包中的方法编写mock代码

Unit testing 如何为另一个包中的方法编写mock代码,unit-testing,go,Unit Testing,Go,我正在为服务设置服务测试。转到服务。转到 在service.go中,从dao.go调用方法 所以我需要模拟这个dao方法。 但是我不知道如何编写这个模拟方法。 这是存储库结构。 article ├ client ├ api │ ├ main.go │ ├ contoroller │ │ └ contoroller.go │ ├ service │ │ └ service.go │ ├ dao │ │ └ dao.go │

我正在为
服务设置
服务测试。转到
服务。转到

service.go
中,从
dao.go
调用方法
所以我需要模拟这个dao方法。
但是我不知道如何编写这个模拟方法。

这是存储库结构。

article
  ├ client
  ├ api
  │  ├ main.go
  │  ├ contoroller
  │  │    └ contoroller.go
  │  ├ service
  │  │    └ service.go
  │  ├ dao
  │  │    └ dao.go
  │  ├ go.mod 
  │  ├ go.sum
  │  └ Dockerfile
  ├ nginx
  └ docker-compose.yml
加油

func GetArticleService(db*sql.db)[]util.Article{
var articles[]util.Article
//我想模拟dao.GetArticleDao(db)
结果:=dao.GetArticleDao(db)
第条:=util.article{}
查找结果。下一步(){
错误:=results.Scan(&article.ID,&article.UUID,&article.TITLE,&article.CONTENT)
如果错误!=零{
死机(err.Error())
}否则{
文章=附加(文章,文章)
}
}
归还物品
}
服务测试

func TestGetArticleService(t*testing.t){
//模拟数据库
db,3;,err:=sqlmock.New()
如果错误!=零{
t、 Fatalf(“打开存根数据库连接时不应出现错误“%s”,err)
}
延迟db.Close()
//创造期望值
var expectedArticles[]util.Article
expectedArticle1:=util.Article{
ID:1,
UUID:“bea1b24d-0627-4ea0-aa2b-8af4c6c2a41c”,
标题:“测试”,
内容:“测试”,
}
expectedArticles=append(expectedArticles,expectedArticle1)
expectedArticle2:=util.Article{
ID:2,
UUID:“844bc620-7336-41a3-9cb4-552a0024ff1c”,
标题:“测试2”,
内容:“test2”,
}
expectedArticles=append(expectedArticles,expectedArticle2)
//检查期望值和GetArticleService(db)是否相等。
//由于执行了GetArticleService(db),所以我想模拟dao.GetArticleDao(db)
assert.Equal(t,expectedArticles,GetArticleService(db))
}
我想在
service.go中模拟
dao.GetArticleDao(db)
以通过
service\u测试。go


但是我不知道如何模拟这段代码。
因此,要做到这一点,您需要对实际代码的定义更加抽象,这允许您替换对第三方模块的调用以进行测试

下面类似的内容将允许您将dao函数替换为具有相同签名的测试模拟函数。一旦你定义了一个硬类型或函数调用,你就可以永久地绑定这个函数/类型

func GetArticleService(getArticleDao func(*sql.DB) (string), db *sql.DB) []util.Article {
    var articles []util.Article

    // this is the mock, at this point you can pass in a mock function for testing
    results := getArticleDao(db)

    article := util.Article{}
    for results.Next() {
        err := results.Scan(&article.ID, &article.UUID, &article.TITLE, &article.CONTENT)
        if err != nil {
            panic(err.Error())
        } else {
            articles = append(articles, article)
        }
    }
    return articles
} 

不要嘲笑。使这些东西成为显式依赖项(例如函数参数),并在测试期间提供一个伪/存根。模拟偶数测试是为了什么?返回[]T的方法确实返回[]T吗?