【问题标题】:How do I unit test socket code with PHPUnit?如何使用 PHPUnit 对套接字代码进行单元测试?
【发布时间】:2012-02-26 12:37:54
【问题描述】:

我目前有一个 Socket 类,它基本上只是 PHP 的 socket_* 函数的 OO 包装类:

class Socket {
    public function __construct(...) {
        $this->_resource = socket_create(...);
    }

    public function send($data) {
        socket_send($this->_resource, $data, ...);
    }

    ...
}

我认为我不能模拟套接字资源,因为我使用的是 PHP 的套接字函数,所以现在我不知道如何可靠地对这个类进行单元测试。

【问题讨论】:

  • 据我所知,省略的部分...很重要
  • @KingCrunch:它们很重要,因为它们是我想要测试的,但对我的问题并不重要。因为socket_* 函数依赖于套接字资源(AFAIK 无法模拟),所以我无法可靠地测试这些方法。
  • 我对一般的单元测试网络代码有一些看法,但我对 PHP 的经验为零。如果你这几天没有收到 PHP 开发者的任何回复,那我就写一些 cmets。如果您发布一些使用您的套接字类的代码会很有帮助,因为这可能会被考虑到我的答案中。
  • 根据我的回答,我认为这个问题可能存在严重缺陷。如果我的答案甚至不在正确的范围内,您应该考虑对其进行大幅修改。
  • 请参阅stackoverflow.com/questions/11280506/…,在那里我遇到了类似的问题,最后得到的代码显示了如何模拟 PHP 的内置函数。

标签: php unit-testing sockets phpunit


【解决方案1】:

您似乎遗漏了单元测试思维的一小部分。

您的问题很容易通过创建一个存根对象来解决。奇怪的是,我一次又一次地给出这个答案,所以它一定被很多人错过了。

因为我看到如此对存根和模拟之间的区别感到困惑,所以让我在这里也列出来......

  • 模拟是一个类扩展另一个类,测试直接依赖,以便将该类的行为更改为让测试更容易
  • 存根是一个*实现 API 或接口**的类,测试无法直接对其进行轻松测试,以便使测试成为可能

^-- 这是我读过的对这两个最清晰的描述;我应该把它放在我的网站上。

套接字有一个很好的功能,您可以绑定到端口 0 以进行测试(说真的,它被称为“临时端口”)。

所以试试这个:

class ListeningServerStub
{
    protected $client;

    public function listen()
    {
        $sock = socket_create(AF_INET, SOCK_STREAM, 0);

        // Bind the socket to an address/port
        socket_bind($sock, 'localhost', 0) or throw new RuntimeException('Could not bind to address');

        // Start listening for connections
        socket_listen($sock);

        // Accept incoming requests and handle them as child processes.
        $this->client = socket_accept($sock);
    }

    public function read()
    {
        // Read the input from the client – 1024 bytes
        $input = socket_read($this->client, 1024);
        return $input;
    }
}

创建此对象并将其设置为在您的测试的setUp() 中侦听并停止侦听并在tearDown() 中销毁它。然后,在您的测试中,连接到您的假服务器,通过 read() 函数取回数据,然后进行测试。

如果这对您有很大帮助,请考虑给我一个赏金,让我跳出传统框框思考;-)

【讨论】:

  • 我认为您没有理解我的问题。也许不清楚是我的错(如果是这样,请告诉我如何修改它以使其更好)。我要测试的代码 服务器,因此对服务器进行存根对我没有帮助。也不会对客户端进行存根,因为正如我所指出的,即使存根也会依赖于外部资源(很像单元测试文件系统代码)。
  • 我想更清楚一点:如果我存根客户端会发生什么,但防火墙阻止了所选端口上的网络流量。或者某些 PHP 设置不允许打开套接字。或者我们在没有 root 的系统上选择一个
  • @drrcknlsn 如果您需要帮助对不属于您的 Socket 类的服务器进行单元测试,那么您对单元测试的内容非常困惑。如果您想测试服务器,那么只需切换到存根客户端(显然!)。如果以上都不是,不仅问题不好,而且我完全糊涂了,呃。
  • 嗯,伙计。这一切都在测试本地主机。您的单元测试只需要依赖于没有任何严重错误的本地网络堆栈。
  • 优秀的西奥多,我正是在寻找这样的解决方案
猜你喜欢
  • 2011-06-06
  • 1970-01-01
  • 1970-01-01
  • 2023-03-06
  • 2013-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多