【问题标题】:Golang net package mockingGolang 网包 mocking
【发布时间】:2014-07-03 23:47:35
【问题描述】:

我正在尝试学习在我的个人项目中使用 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
}

任何人都可以给我任何提示如何去测试这样的代码?

谢谢

【问题讨论】:

    标签: unit-testing testing go


    【解决方案1】:

    简短的回答是你不能嘲笑这样的事情。 Go 是一种静态编译语言,因此与 ruby​​ 或其他动态语言不同,它不支持在运行中神奇地重写固定函数调用。

    如果你真的想测试它,你有两个明显的选择:

    • 定义 NewThingy 以获取类型匹配 net.InterfaceByName 的函数指针。将该函数传递给对该函数的所有“真实”调用,但在测试中传递一个虚拟函数指针。但是,这会稍微减慢代码的速度,而且读起来也不愉快。

    • 要求您的测试环境使用合法数据。根据您的要求可能会也可能不会,但有一些软件包可能会有所帮助(我写了https://github.com/eapache/peroxide 用于类似目的,但它不处理接口,所以它可能不是您想要的)。

    【讨论】:

    • 是的,我想这可能并不容易。我读了一些博客文章,例如nathany.com/go-testing-toolbox,它们确实建议了第 1 点,即依赖注入,但这需要对我的代码进行全面重构。我找不到任何对我的用例有用的东西。您的软件包用于测试网络服务。我需要模拟创建和销毁设备等。
    • 依赖注入是第一个项目符号中描述的内容。这绝对是编写 Go 代码(以及所有其他面向对象代码)的惯用方式。这是一个简化版:play.golang.org/p/oBjtKqGShX
    【解决方案2】:

    这不是您问题的直接答案,但Gomock 通过为您提供的任何接口生成代码来提供模拟。要使用它,您需要使用基于接口的编码风格,而不是直接依赖结构。

    因为许多标准库包都使用接口,所以用 Gomock 模拟它们是有效的。对于任何不这样做的,您可能需要编写一个(未经测试的)垫片来提供必要的接口层。这对我来说似乎没有传递函数指针以实现类似效果的想法那么混乱。

    【讨论】:

    【解决方案3】:

    我遇到了同样的问题,最终使用这个包来模拟: 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)
    

    【讨论】:

      猜你喜欢
      • 2016-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-10
      • 2018-09-04
      • 2022-11-24
      相关资源
      最近更新 更多