我试图学习在golang的个人项目中编写测试。
我的项目中的一些函数正在使用net
包,但是由于我是新手,我不知道如何模拟net
等包中的函数与主机设备交互的一个。
为了使我的问题更具体,我有一个类似的功能:
func NewThingy(ifcName string) (*Thingy, error) {
if ifc, err := net.InterfaceByName(ifcName); err == nil {
return nil, fmt.Errorf("Interface name %s already assigned on the host", ifcName)
}
....
return &Thingy{
ifc: ifc,
}, nil
}
Thingy明确定义为:
type Thingy struct {
ifc *net.Interface
}
任何人都可以给我任何提示如何测试这样的代码?
由于
答案 0 :(得分:2)
简短的回答是,你不能嘲笑这样的事情。 Go是一种静态编译的语言,因此与ruby或其他动态语言不同,它不支持动态地重写固定函数调用。
如果你真的想测试它,你有两个明显的选择:
定义NewThingy
以获取类型与net.InterfaceByName
匹配的函数指针。将该函数传递给函数的所有“实际”调用,但在测试中传递一个虚函数指针。但这会稍微减慢代码速度,并且读取或写入效果不佳。
要求您的测试环境使用合法数据。根据您的要求可能会或可能不会,但有一些软件包可能有所帮助(我为了类似的目的写了https://github.com/eapache/peroxide,但它没有处理接口,所以它可能不是你想要的)。
答案 1 :(得分:1)
这不是您问题的直接答案,但Gomock通过为您提供的任何界面生成代码来提供模拟。要使用它,您需要使用基于接口的编码样式,而不是直接依赖于结构。
由于许多标准库包使用接口,因此使用Gomock模拟它们是有效的。对于任何不这样做的人,您可能需要编写一个(未经测试的)垫片来提供必要的接口层。对于我而言,这似乎比传递函数指针以实现类似效果的想法更为混乱。
答案 2 :(得分:0)
我遇到了同样的问题,最终使用这个包来模拟: https://github.com/foxcpp/go-mockdns
srv, _ := mockdns.NewServer(map[string]mockdns.Zone{
"example.org.": {
A: []string{"1.2.3.4"},
},
}, false)
defer srv.Close()
srv.PatchNet(net.DefaultResolver)
defer mockdns.UnpatchNet(net.DefaultResolver)
addrs, err := net.LookupHost("example.org")
fmt.Println(addrs, err)
它还具有创建模拟解析器对象的选项,但是您必须使用依赖注入来注入要在内部使用的模拟解析器:
r := mockdns.Resolver{
Zones: map[string]mockdns.Zone{
"example.org.": {
A: []string{"1.2.3.4"},
},
},
}
addrs, err := r.LookupHost(context.Background(), "example.org")
fmt.Println(addrs, err)