Unit testing 如何在同一结构中的另一个方法中调用存根方法

Unit testing 如何在同一结构中的另一个方法中调用存根方法,unit-testing,go,Unit Testing,Go,代码如下: package main import ( "fmt" ) type Connector struct {} func (c *Connector) Pool() (interface{}, error) { err := c.ping() if err != nil { fmt.Println("error handle logic"); return nil, err } fmt.Println("success logic") re

代码如下:

package main

import (
  "fmt"
)

type Connector struct {}

func (c *Connector) Pool() (interface{}, error) {
  err := c.ping()
  if err != nil {
    fmt.Println("error handle logic");
    return nil, err
  }
  fmt.Println("success logic")
  return 1, nil
}

func (c *Connector) ping() error {
  var err error
  // err = some side-effect RPC operation
  if err != nil {
    return err
  }
  return nil
}
现在,我想测试
Connector
struct的
Pool
方法。由于
ping
方法有一些副作用的RPC操作,因此我需要存根它及其返回值,以便可以测试
池中的每个代码分支

成功测试用例伪代码:

Stub(c,“ping”)。返回值(nil)
c、 池()
Expect(fmt.Println).ToBeCalledWith(“成功逻辑”)
故障测试用例伪代码:

Stub(c,“ping”).Return(errors.New(“test”))
c、 池()
Expect(fmt.Println).ToBeCalledWith(“错误句柄逻辑”)
我们需要遵循,这将使代码更易于测试

细节(具体实现)应取决于抽象

重构代码:

连接器。转到

封装连接器
进口(
“fmt”
)
类型Pinger接口{
Ping()错误
}
类型连接器结构{
DB Pinger
}
func(c*连接器)池()(接口{},错误){
错误:=c.DB.Ping()
如果错误!=零{
fmt.Println(“错误处理逻辑”)
返回零,错误
}
fmt.Println(“成功逻辑”)
返回1,无
}
现在,创建mocked DB,它使用包实现
Pinger
接口。然后,将这个模拟数据库传递给连接器,这是某种依赖注入

然后我们可以使用不同的返回值“mock”
Ping
方法

连接器\u测试。开始

package connector\u测试
进口(
“fmt”
“测试”
连接器“github.com/mrdulin/golang/src/stackoverflow/62035606”
“github.com/stretchr/authentic/mock”
“github.com/stretchr/authentic/require”
)
类型MockedDB结构{
模仿,模仿
}
func(db*MockedDB)Ping()错误{
args:=db.Called()
返回参数。错误(0)
}
func TestConnector_池(t*testing.t){
t、 运行(“应验证与数据库的连接是否仍处于活动状态”,func(t*testing.t){
testDB:=new(MockedDB)
c:=连接器。连接器{DB:testDB}
testDB.On(“Ping”)。返回(无)
池,错误:=c.pool()
无(t,err,Nil)
要求相等(t,1,池)
})
t、 Run(“如果与数据库的连接未激活,则应返回错误”),func(t*testing.t){
testDB:=new(MockedDB)
c:=连接器。连接器{DB:testDB}
testDB.On(“Ping”).返回(fmt.Errorf(“网络”))
池,错误:=c.pool()
require.Error(t,err,“网络”)
无(t,池)
})
}
单元测试结果:

==运行TestConnector\u池
===运行TestConnector\u Pool/should\u验证\u到\u的连接\u数据库\u仍然处于活动状态
成功逻辑
===运行TestConnector\u Pool/如果连接到数据库的连接未激活,则应返回错误
错误处理逻辑
---通过:测试连接器\u池(0.00s)
---通过:TestConnector\u Pool/should\u验证\u到\u的连接\u数据库\u是否仍处于活动状态(0.00s)
---通过:TestConnector\u Pool/如果连接到数据库未激活(0.00s),则应返回错误
通过
覆盖率:100.0%的报表
ok github.com/mrdulin/golang/src/stackoverflow/62035606 0.364s
覆盖率报告:

我们需要遵循,这将使代码更易于测试

细节(具体实现)应取决于抽象

重构代码:

连接器。转到

封装连接器
进口(
“fmt”
)
类型Pinger接口{
Ping()错误
}
类型连接器结构{
DB Pinger
}
func(c*连接器)池()(接口{},错误){
错误:=c.DB.Ping()
如果错误!=零{
fmt.Println(“错误处理逻辑”)
返回零,错误
}
fmt.Println(“成功逻辑”)
返回1,无
}
现在,创建mocked DB,它使用包实现
Pinger
接口。然后,将这个模拟数据库传递给连接器,这是某种依赖注入

然后我们可以使用不同的返回值“mock”
Ping
方法

连接器\u测试。开始

package connector\u测试
进口(
“fmt”
“测试”
连接器“github.com/mrdulin/golang/src/stackoverflow/62035606”
“github.com/stretchr/authentic/mock”
“github.com/stretchr/authentic/require”
)
类型MockedDB结构{
模仿,模仿
}
func(db*MockedDB)Ping()错误{
args:=db.Called()
返回参数。错误(0)
}
func TestConnector_池(t*testing.t){
t、 运行(“应验证与数据库的连接是否仍处于活动状态”,func(t*testing.t){
testDB:=new(MockedDB)
c:=连接器。连接器{DB:testDB}
testDB.On(“Ping”)。返回(无)
池,错误:=c.pool()
无(t,err,Nil)
要求相等(t,1,池)
})
t、 Run(“如果与数据库的连接未激活,则应返回错误”),func(t*testing.t){
testDB:=new(MockedDB)
c:=连接器。连接器{DB:testDB}
testDB.On(“Ping”).返回(fmt.Errorf(“网络”))
池,错误:=c.pool()
require.Error(t,err,“网络”)
无(t,池)
})
}
单元测试结果:

==运行TestConnector\u池
===运行TestConnector\u Pool/should\u验证\u到\u的连接\u数据库\u仍然处于活动状态
成功逻辑
===运行TestConnector\u Pool/如果连接到数据库的连接未激活,则应返回错误
错误处理逻辑
---通过:测试连接器\u池(0.00s)
---通过:TestConnector\u Pool/should\u验证\u到\u的连接\u数据库\u是否仍处于活动状态(0.00s)
---通过:TestConnector\u Pool/如果连接到数据库未激活(0.00s),则应返回错误
通过
覆盖率:100.0%的报表
ok github.com/mrdulin/golang/src/stackoverflow/62035606 0.364s
覆盖率报告:


你不能,不是一个具体类型的方法。@mkopriva你能给我一些关于为什么不能模拟/存根一个具体类型的方法的文章/博客吗?谢谢。语言不允许这样。这是唯一的原因。而不是存根/嘲笑