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