如何使用PHPUnit对套接字代码进行单元测试?

时间:2012-02-03 22:26:38

标签: php unit-testing sockets phpunit

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

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

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

    ...
}

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

1 个答案:

答案 0 :(得分:16)

你似乎错过了单位测试思维的一小部分。

通过创建Stub对象可以轻松解决您的问题。奇怪的是,我一次又一次地给出这个答案,所以很多人都会错过这个答案。

因为我看到这么多关于存根和模拟之间的差异的混淆,所以让我把它放在这里,以及...

  • 模拟扩展另一个类的类,测试直接依赖,以便更改该类的行为< strong>使测试更容易。
  • 存根是*实现API或接口**的类,测试无法直接自行测试,以便使测试成为可能。< / LI>

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

套接字有这个很好的功能,你可以绑定到端口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 &#8211; 1024 bytes
        $input = socket_read($this->client, 1024);
        return $input;
    }
}

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

如果这对你有很多帮助,可以考虑给我一个在传统方框外思考的赏金; - )