How do I unit test socket code with PHPUnit?

夙愿已清 提交于 2019-12-21 04:17:04

问题


I currently have a Socket class, which is basically just an OO wrapper class for PHP's socket_* functions:

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

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

    ...
}

I don't think I can mock the socket resource since I'm using PHP's socket functions, so right now I'm stuck as to how to reliably unit test this class.


回答1:


You appear to be missing a small piece to the unit test mindset.

Your problem is easily solvable by creating a Stub object. Strangely, I give this answer time and time again, so it must be largely missed by a lot of people.

Because I see so much confusion as to the differences between stubs and mocks, let me lay it out here, as well...

  • A mock is a class that extends another class that the test is directly dependent on, in order to change behaviors of that class to make testing easier.
  • A stub is a class that *implements an API or interface** that a test cannot test easily directly on its own, in order to make testing possible.

^-- That is the clearest description of the two I've ever read; I should put it on my site.

Sockets have this nice feature where you can bind to port 0 for testing purposes (seriously, it's called the "ephemeral port").

So try this:

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;
    }
}

Create this object and set it to listen in your test's setUp() and stop listening and destroy it in the tearDown(). Then, in your test, connect to your fake server, get the data back via the read() function, and test that.

If this helps you out a lot, consider giving me a bounty for thinking outside the traditional box ;-)



来源:https://stackoverflow.com/questions/9136366/how-do-i-unit-test-socket-code-with-phpunit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!