【问题标题】:Testing constructors in Go在 Go 中测试构造函数
【发布时间】:2015-12-01 22:34:57
【问题描述】:

如何为我的Client 结构测试我的NewClient 构造函数?

package busybus

import (
    "bufio"
    "net"
)

type Client struct {
    counter  integer
    conn     net.Conn
    bufin    *bufio.Reader
    bufout   *bufio.Writer
    messages chan string
    state    string
}

func NewClient(conn net.Conn, messages chan string) *Client {
    return &Client{
        counter:  0,
        conn:     conn,
        bufin:    bufio.NewReader(conn),
        bufout:   bufio.NewWriter(conn),
        messages: messages,
        state:    "waiting",

    }
}

我尝试了一些这样的测试:

package busybus

import (
    "net"
    "testing"
)

func TestNewClient(t *testing.T) {
    ln, _ := net.Listen("tcp", ":65535")
    conn, _ := ln.Accept()
    messages := make(chan string)

    client := NewClient(conn, messages)
    if client.conn != conn {
        t.Errorf("NewClient(%q, %q).conn == %q, want %q", conn, messages, client.conn, conn)
    }
}

但是由于ln.Accept,这在测试运行期间挂起,无论如何这似乎是一个完全错误的方法......有什么建议我可以测试这个构造函数吗?

【问题讨论】:

    标签: unit-testing testing go


    【解决方案1】:

    有些代码非常简短,以至于确保测试正确比确保代码本身正确更复杂。 你的构造函数就是这样的代码。

    我要做的要么根本不测试它,要么只是调用它(使用net.Conn 的一些虚拟实现)以确保它在调用时不会冒烟(因此称为烟雾测试)。

    稍后您可以将其作为更大测试(集成测试)的一部分进行测试,您可以在其中连接一个真实的服务器,并使用您的客户端结构与之对话。

    如果您发现由于此构造函数导致的错误,请首先添加一个测试来演示该问题,然后修复它。然后您将进行测试:-)

    测试应该检查构造函数是否“按预期工作”。检查client.conn 的值几乎不会检查任何预期的行为,因为未导出字段的值不是行为。它只是检查结构和构造函数是如何实现的,而不是它实现了什么。测试什么,而不是如何。

    顺便说一句,您可以在客户端中嵌入 *ReadWriter。

    client.buf = bufio.NewReadWriter(...)
    

    【讨论】:

    • 感谢您对读者的建议。除此之外我不同意。当然,这是一个简单的构造函数,由于它的简单性甚至没有必要,但是当我有一些更复杂的初始化过程时,我想首先检查它,而不是稍后搜索我的验收测试失败的原因。你写了一个虚拟连接,你的意思是简单地满足 net.Conn 接口吗?
    • @astropanic:你写了“但是当我有一些更复杂的初始化过程时”:目前你没有它。为什么现在要为可能永远不会发生的事情烦恼?您的构造函数只返回一个填充的结构。只是测试一下。无需在测试中痴迷。
    【解决方案2】:

    除了@bjarke-ebert 所说的。

    Go 中没有构造函数,它们只是普通函数。像测试任何其他功能一样测试它们。如果一个功能太复杂而无法测试,那么可能有一种方法可以更改设计以使其更易于测试。

    根据我的经验,过多检查内部实现细节的测试(例如问题中的测试)很难维护,因为它们需要不断更新。

    【讨论】:

    • 构造函数也不是普通函数吗?你建议什么而不是我的函数来初始化 struct ?假设我有一些代码需要初始化更多这样的客户端结构。我认为如果没有这个功能,当功能需要更改时,我以后会有更多代码要重写?我在不同的 Golang 项目中多次看到这种模式,并且读到使用 New 或 NewType 是一种常见的做法,也许我错了(仍在学习 Go),我愿意接受建议,thx
    • 您的问题明确询问如何测试构造函数。我只是指出您应该将它们作为任何其他功能进行测试。在您提供的示例中使用NewClient 功能非常有意义。
    • 再详细一点:NewClient 函数没问题。但是测试由 NewClient 初始化的 conn 字段没有任何意义,因为它应该已经被其他测试间接测试过。测试不是免费的。您需要编写它们,使它们保持最新,它们会增加测试套件的执行时间,等等。
    猜你喜欢
    • 2012-12-29
    • 2013-09-28
    • 2013-08-10
    • 2022-01-24
    • 1970-01-01
    • 1970-01-01
    • 2018-09-27
    • 1970-01-01
    • 2019-11-27
    相关资源
    最近更新 更多