当前位置: 首页 > 面试题库 >

如何在不创建实际网络连接的情况下测试依赖net.Conn的代码?

桑坚成
2023-03-14
问题内容

如果我有与一起使用的代码net.Conn,如何在不实际创建与localhost的网络连接的情况下为其编写测试?

我在网上没有看到任何解决方案。人们似乎忽略了它(没有测试),编写了不能并行运行的测试(即使用实际的网络连接,使用了端口),或者使用了io.Pipe。

然而,net.Conn限定SetReadDeadlineSetWriteDeadline; 而io.Pipe没有。net.Pipe
没有,尽管从表面上声称实现了该接口,但它只是通过以下方式实现:

func (p *pipe) SetDeadline(t time.Time) error {
    return &OpError{Op: "set", Net: "pipe", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}

func (p *pipe) SetReadDeadline(t time.Time) error {
    return &OpError{Op: "set", Net: "pipe", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}

func (p *pipe) SetWriteDeadline(t time.Time) error {
    return &OpError{Op: "set", Net: "pipe", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}

(请参阅:https :
//golang.org/src/net/pipe.go)

那么…还有其他方法可以做到吗?

我将接受任何显示如何在测试截止时间(不是实际的网络套接字)中使用流的答案。

理想情况下,此cloudflare博客文章涵盖了使用截止日期的动机,以及为什么在每个连接的goroutine中永远阻塞不是可接受的解决方案;但是不管那种说法如何,尤其是在这种情况下,我正在寻找一种
针对测试 的解决方案,我们故意想要处理连接不良的情况下等)

(注意。这似乎是Go中Simulatetcp连接的复制品,但请注意,该问题中提出的所有解决方案均未实现Deadline函数,这正是我要问的此处测试方法)


问题答案:

您的问题很开放,因此不可能给您“正确答案”。但是我想我理解您遇到的困难。这个答案也是开放的,但是它应该使您回到正确的轨道上。

几天前,我写了一篇简短的文章,其中显示了您必须使用的原理。

在我举一些小例子说明您的测试如何工作之前,我们需要修正一个重要点:

我们 不测试网络包装 。我们假设 该文件包没有错误 ,但确实如此。这意味着 我们不在乎Go团队如何实现
SetReadDeadline实现SetWriteDeadline。我们仅在程序中测试用法。

步骤1:重构代码

您没有发布任何代码段,因此我仅举一个简单的示例。我猜你有一个方法或函数,正在使用net包。

func myConn(...) error {
  // You code is here
  c, err := net.Dial("tcp", "12.34.56.78:80")
  c.setDeadline(t)
  // More code here
}

能够测试您需要重构功能的功能,因此它仅使用net.Conn接口。为此,必须将net.Dial()调用移到函数之外。请记住,我们不想测试net.Dial函数。

新功能可能如下所示:

func myConn(c, net.Conn, ...) error {
  // You code is here
  c.setDeadline(t)
  // More code here
}

步骤2:实现net.Conn接口

为了进行测试,您需要实现net.Conn接口:

type connTester struct {
    deadline time.Time
}

func (c *connTester) Read(b []byte) (n int, err error) {
    return 0, nil
}

...

func (c *connTester) SetDeadline(t time.Time) error {
    c.deadline = t
    return nil
}

...

完整的实现,包括小的类型检查:https :
//play.golang.org/p/taAmI61vVz

步骤3:测试

在测试时,我们并不关心Dial()方法,我们只是创建一个指向我们的测试类型的指针,该指针实现了net.Conn接口并将其放入您的函数中。然后,如果最后期限参数设置正确,我们将查看测试用例。

func TestMyConn(t *testing.T){
  myconnTester = &connTester{}
  err := myConn(myconnTester,...)
  ...
  if myconntester.deadline != expectedDeadline{
  //Test fails
  }
}

因此,在测试时,您应该始终考虑要测试的功能。我认为对您真正想要编写的功能进行抽象是最困难的部分。在简单的单元测试中,您永远不要测试标准库的功能。希望这个例子可以帮助您重新走上正轨。



 类似资料:
  • 本文向大家介绍如何在不使用HTML的情况下创建网站?,包括了如何在不使用HTML的情况下创建网站?的使用技巧和注意事项,需要的朋友参考一下 如果您不了解HTML或CSS,并且想创建一个网站,那么不用担心,您可以轻松创建网站,而无需编写一行HTML代码。 以下是一些无需编写任何HTML或代码行即可构建网站的方法: 网站构造函数 当您购买网站托管计划时,托管公司将为您提供免费的网站构建器选项,以轻松创

  • 查看我的Raku代码,我意识到我几乎从不使用块来实际捕获/处理错误。相反,我用块处理错误,并测试未定义的值;我唯一使用的块就是以不同的方式记录错误。我似乎并不是唯一一个有这种习惯的人——看看Raku文档中的块,除了打印消息之外,几乎没有一个能处理任何意义上的错误。(Rakudo中的大多数块也是如此。)。 然而,我想更好地理解如何使用块。让我介绍几个示例函数,所有这些函数都基于以下基本思想: 现在,

  • 是否可以从Ecore元模型生成Java代码,而不依赖EMF?生成“干净的代码”,就像它是从UML模型生成的一样。

  • 问题内容: 有没有一种方法可以在Windows上模拟Retina显示屏,以测试网站上是否有HiDPI显示屏(例如Retina)? 我在标准的24英寸1920x1080显示器上运行Windows。昨晚,我在朋友全新的15英寸Retina MacBook Pro上检查了自己的网站,图形看上去像是模糊的(比普通的15英寸MacBook差得多),而字体却是超级清晰明了,由于直接比较,徽标显得更糟。 我已按

  • 我尝试为我的数据创建带有“转换”的插件到kafka-connect,并将其与不同的接收器连接器一起使用。当我安装插件时,kafka-connect看不到我的类。 我使用kafka connect maven插件创建了我的捆绑包zip。使用confluent hub(来自本地文件)的安装已成功。 所有文件都已解压,我的工作者属性已更新插件。路径。我在分布式模式下运行connect,并尝试从包中创建带

  • 我正在寻找一种方法来刷新我的渐变依赖关系,而不必重新生成项目。我正在使用智能和它的渐变包装器。我尝试过从 IntelliJ 的 gradle UI 运行任务“依赖关系”,我尝试过运行命令 和 ,两者都不起作用。让 gradle 下载新依赖项的唯一方法是使用来自 IntelliJ UI ,但我不喜欢这样做,因为 gradle 会自动运行一些我不想运行的任务,而我只想刷新依赖项。