在Go中模拟tcp连接
在 Go 中,TCP 连接 (net.Conn) 是 io.ReadWriteCloser。我想通过模拟 TCP 连接来测试我的网络代码。我有两个要求:
- 每当写入数据时,要读取的数据都存储在字符串中
- ,我希望将其存储在稍后可以访问的某种缓冲区中
是否有为此的数据结构,或者一种简单的制作方法?
In Go, a TCP connection (net.Conn) is a io.ReadWriteCloser. I'd like to test my network code by simulating a TCP connection. There are two requirements that I have:
- the data to be read is stored in a string
- whenever data is written, I'd like it to be stored in some kind of buffer which I can access later
Is there a data structure for this, or an easy way to make one?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
不知道在提出问题时是否存在这种情况,但您可能需要
net.Pipe()
它为您提供两个全双工net.Conn
实例,它们链接到每个实例其他No idea if this existed when the question was asked, but you probably want
net.Pipe()
which provides you with two full duplexnet.Conn
instances which are linked to each other编辑:我已将这个答案打包到一个包中,这使事情变得更简单 - 请参阅此处:https://github.com/jordwest/mock-conn
虽然 Ivan 的解决方案适用于简单的情况,但请记住,真正的 TCP 连接实际上是两个缓冲区,或者更确切地说是管道。例如:
如果您使用服务器既可以读取又可以写入的单个缓冲区,则最终可能会导致服务器自言自语。
这里有一个解决方案,允许您将
MockConn
类型作为ReadWriteCloser
传递到服务器。Read
、Write
和Close
函数只是代理到服务器管道端的函数。当模拟“服务器”连接时,只需传递 MockConn 代替您将使用 net.Conn 的位置(这显然仅实现了 ReadWriteCloser 接口,您可以轻松添加
LocalAddr()
的虚拟方法(如果您需要支持完整的net.Conn
接口))在测试中,您可以通过读取和写入
来充当客户端根据需要 >ClientReader
和ClientWriter
字段:EDIT: I've rolled this answer into a package which makes things a bit simpler - see here: https://github.com/jordwest/mock-conn
While Ivan's solution will work for simple cases, keep in mind that a real TCP connection is actually two buffers, or rather pipes. For example:
If you use a single buffer that the server both reads from and writes to, you could end up with the server talking to itself.
Here's a solution that allows you to pass a
MockConn
type as aReadWriteCloser
to the server. TheRead
,Write
andClose
functions simply proxy through to the functions on the server's end of the pipes.When mocking a 'server' connection, simply pass the MockConn in place of where you would use the
net.Conn
(this obviously implements theReadWriteCloser
interface only, you could easily add dummy methods forLocalAddr()
etc if you need to support the fullnet.Conn
interface)In your tests you can act as the client by reading and writing to the
ClientReader
andClientWriter
fields as needed:为什么不使用bytes.Buffer?它是一个 io.ReadWriter 并具有一个 String 方法来获取存储的数据。如果您需要将其设为 io.ReadWriteCloser ,您可以定义自己的类型:
并定义一个 Close 方法:
Why not using
bytes.Buffer
? It's anio.ReadWriter
and has aString
method to get the stored data. If you need to make it anio.ReadWriteCloser
, you could define you own type:and define a
Close
method:在大多数情况下,您不需要模拟 net.Conn。
您只需要模拟那些会增加测试时间、阻止测试并行运行(使用硬编码文件名等共享资源)或可能导致中断(您可能会耗尽连接限制或端口,但在大多数情况下)的内容。当您单独运行测试时,这不是问题)。
不模拟的优点是可以更精确地测试您想要用真实事物测试的内容。
https://www.accenture.com/us-en/blogs/software-engineering-blog/to-mock-or-not-to-mock-is-that-even-a-question< /a>
您可以编写一个模拟服务器,在测试中的 goroutine 中运行它,然后使用真实的 net.Conn 连接到它,而不是模拟 net.Conn
一个快速而肮脏的示例:
In majority of the cases you do not need to mock net.Conn.
You only have to mock stuff that will add time to your tests, prevent tests from running in parallel (using shared resources like the hardcoded file name) or can lead to outages (you can potentially exhaust the connection limit or ports but in most of the cases it is not a concern, when you run your tests in isolation).
Not mocking has an advantage of more precise testing of what you want to test with a real thing.
https://www.accenture.com/us-en/blogs/software-engineering-blog/to-mock-or-not-to-mock-is-that-even-a-question
Instead of mocking net.Conn, you can write a mock server, run it in a goroutine in your test and connect to it using real net.Conn
A quick and dirty example: