2015-12-01 72 views
0

如何测试我的NewClient构造函数是否适用于我的Client结构?在Go中测试构造函数

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在试运行期间该挂起,这似乎是一个完全错误的做法反正...任何建议如何测试这个构造?

回答

2

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

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

稍后,您可以将其作为更大测试(集成测试)的一部分进行测试,您需要一台真正的服务器进行连接,并使用您的客户端结构与其交流。

如果您发现由此构造函数引起的错误,请首先添加一个演示此问题的测试,然后对其进行修复。然后你会有你的测试:-)

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

顺便说一下,你可能会在你的客户端中嵌入一个* ReadWriter。

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

感谢您对读者的建议。除此之外,我不同意。当然,这是一个简单的构造函数,由于它的简单性,它甚至不是必需的,但是当我有一些更复杂的初始化过程时,我想首先检查它,而不是稍后搜索我的验收测试失败的原因。你写了一个虚拟连接,你的意思是简单地满足net.Conn接口吗? – astropanic

+1

@astropanic:你写过“但当我有一些更复杂的初始化过程”:目前你没有它。为什么现在打扰一些可能从未发生过的事情?你的构造函数只返回一个填充的结构体。只是测试一下。在测试中不需要迷恋。 – Volker

1

除了@ bjarke-ebert所说的。

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

另外从我的经验来看,太多检查内部实现细节的测试(如来自问题的测试)非常难以维护,因为它们经常需要更新。

+0

是一个构造函数不是一个正常的功能呢?你在暗示什么,而不是我的函数来初始化结构?假设我有一些代码需要初始化更多这样的客户结构。我认为如果没有这个功能,当功能需要更改时,我以后会有更多的代码来重写。我在不同的Golang项目中看到过这种模式很多次,并且阅读它是使用New或NewType的常见做法,也许我错了(仍然在学习Go),我愿意提供建议,thx – astropanic

+2

您的问题明确询问测试构造函数。我只是提出了一点,你应该测试它们作为其他功能。如你所提供的例子那样拥有'NewClient'函数是非常有意义的。 – kostya

+0

再详细一点:'NewClient'功能没问题。但是测试conn字段是由NewClient初始化的没有任何意义,因为它应该已经被其他测试间接测试过了。测试不是免费的。您需要编写它们,让它们保持最新状态,增加测试套件执行时间等。 – kostya