【问题标题】:Unit testing sockets单元测试套接字
【发布时间】:2011-05-31 10:27:30
【问题描述】:

问候 Stackoverflowers,

我有一个应用程序,其中存在通信抽象层。这一层中的每个实现,称为 connector,为我的应用程序提供了一种与连接的对等方交换数据的方式(例如:通过 HTTP、TCP 套接字、UDP 套接字等)。

例如,我有一个 Connector_Tcp 类,它实现了 readwriteopenclose。

我需要为该类编写一个单元测试。我知道单元测试应该尽可能少的依赖。不幸的是,在这种情况下,依赖是一个系统资源:一个套接字;我无法绕过它。

我需要一些关于如何对这个类进行单元测试的建议。

在我看来,即使这个类正在使用系统资源,也应该像所有其他连接器一样对其进行测试,以确保它符合我的应用程序建立的标准。

我担心诸如绑定冲突(地址已在使用错误)和阻塞之类的事情。我不希望单元测试失败,因为该端口已被与我的应用程序无关的系统服务使用。

我这几天做过很多单元测试,但没有一个依赖于套接字这样的低级资源。

您将如何对依赖于套接字的类进行单元测试?为每个单元打开一个插座?使用单个服务器类,然后使用手动定义的套接字资源连接到它并对其进行测试......?

我想我的问题确实如下:

如果单元测试失败...我怎么知道:

  • 套接字已被另一个进程使用;
  • 单元测试写得不好;或
  • 该方法行为不正确(这是单元测试的价值)。

我需要单元测试来测试方法是否正常运行...

【问题讨论】:

  • 我没有做过任何真正的 PHP 开发,但是你能创建一个从你的 Socket 类派生的模拟类吗?
  • @Dave:我可以。我对每个需要连接器的类都使用模拟对象。我的问题是:我需要测试套接字类本身以确保它尊重抽象层的约定......通过测试模拟对象,它并不能清楚地告诉我套接字类是否有效。
  • 在我看来,单元测试的内容是有实际限制的。我不会尝试对套接字进行单元测试。我想在你的情况下,由于套接字可以在你的应用程序之外访问,你只需要尽你所能围绕连接器编写单元测试并确保它处理所有异常情况。您提到了“地址已在使用”错误,所以我要做的一件事是确保我的连接器不会因为这种情况而死。我会做一个单元测试来创建这个条件并确保它捕捉到它。

标签: php unit-testing sockets


【解决方案1】:

我已经编写了一个类似的抽象层,尽管是在 C/C++ 中,并且我有机会对基于套接字的代码进行单元测试。我不知道这里是否有任何特定于 PHP 的东西,所以我只会提供我能提供的一般性建议。

  • 在您的设置中创建一个服务器套接字,在拆卸时将其关闭。根据您是否支持连接到服务器套接字的多个客户端,您可能希望在测试方法中执行该部分。
  • 假设您可以在客户端代码中指定要连接的端口,让服务器套接字绑定到端口 0(临时端口),然后在客户端代码中使用它。这将消除绑定到已在使用的端口的问题。
  • 在您的套接字上设置超时。如果您的测试由于某些意外原因而失败,您不希望它永远挂起等待连接。
  • 您需要能够交错客户端/服务器行为。例如,您将想要测试如果服务器在客户端读/写过程中关闭其一侧的连接会发生什么。异步 I/O 或多线程都可以完成这项工作。我不确定您在 PHP 中可以使用什么。

【讨论】:

  • 我想我需要 C 程序员的建议,因为 PHP 套接字的处理方式。 PHP 中的套接字函数与 C 套接字非常相似(它们甚至使用相同的常量名!)。话虽如此,我认为你已经为我指明了正确的方向。通过绑定端口 0 并使用getsockname,我可以检索服务器绑定的端口号并将客户端连接到它,而不必担心端口已经被使用。我早该想到的!非常感谢!
  • 哦,对于多线程和多个并发连接,我不必担心。有另一个类负责这个,所以我需要在这里测试套接字本身。
【解决方案2】:

我希望我能正确理解您的问题......如果没有,请告诉我。但我要做的是模拟套接字。这将让您编写一系列单元测试,以确保您的方法在各种情况下都能做正确的事情。

例如,您可以编写一个单元测试,告诉套接字模拟实例抛出“端口不可用”异常。在这种情况下,您可以断言您的方法捕获了异常并使用与异常中相同的文本记录它。

更重要的是,你可以编写一个单元测试,告诉套接字模拟实例从 read() 返回一个有效的字节流,然后你可以断言你的方法做了正确的事情用这些字节。

所以你实际上并没有测试套接字。您正在设置套接字以模拟某些事件,并且您正在测试以查看与套接字一起使用的代码是否在做正确的事情。

(我在 Java、C#、Ruby 和 JavaScript 中使用过模拟框架。我从未使用过 PHP,但我敢打赌,那里有一些很好的模拟框架)。

编辑:是的,那里有一些 PHP 模拟框架。我不能推荐一个,但我能找到几个:PHPUnitLastCraft

【讨论】:

  • 感谢您的回答。我已经在使用 PHPUnit。不幸的是,与我也知道的 Java 和 C# 不同,PHP 中的套接字非常接近 C/C++ 套接字。事实上,PHP 使用 C 库的包装器。 PHP 套接字不是对象,而是被认为是资源(或多或少的指针),它更像是一种原始类型,因此不能被模拟。我的类是这些套接字函数的包装器,我需要确保它们在必要时返回 falsenull 或数据,而不会因为冲突而失败。我认为@axw 可能有我需要的答案。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-05
  • 2023-03-21
  • 1970-01-01
  • 2018-06-18
相关资源
最近更新 更多