PHPUnit testing socket

429 views Asked by At

I want to test socket connection.

socket connection code:

 if (!socket_connect($this->socket, $this->getConfig('host'), $this->getConfig('port'))) {
            throw new ConnectionException("Connection failed: " . $this->getLastError());
        }

Test method:

<?php
require_once '../Webservice.php';
require_once '../Exception/ConnectionException.php';

class WebserviceTest extends PHPUnit_Framework_TestCase
{
    /**
     * @expectedException ConnectionException
     * @expectedExceptionMessageRegExp #Connection failed:.*#
     */
    public function testWebserviceConnectionException()
    {
        $config = array(
            'host' => '127.0.0.1',
            'port' => '23'
        );

        new Webservice($config);
    }
}

In my application everything works fine I've ConnectionException but in phpunit I have:

Failed asserting that exception of type "PHPUnit_Framework_Error_Warning" matches expected exception "ConnectionException". Message was: "socket_connect(): unable to connect [111]: Connection refused".

How I have to test this exception? I'm newbie in phpunit and testing ;(

2

There are 2 answers

0
Pierre Marichez On

I think you should use non-blocking socket to avoid the warning:

socket_set_nonblock ($this->socket)
if (!socket_connect($this->socket, $this->getConfig('host'), $this->getConfig('port'))) {
    throw new ConnectionException(sprintf('Connection failed: %d', $this->getLastError()));
} 

This way, socket_connect() should return false, and not a warning, and the exception will be catch by phpunit.

0
Aleksander Wons On

This happens because many PHP functions rise warnings on failure instead of throwing exception or just returning false. And PHPUnit will, by default, convert PHP errors, warnings, and notices to exceptions.

  1. You have two options. Use set_error_handler to intercept the warning, restore previous error handler with restore_error_handler and throw your own exception. The problem with this solution is that you have to wrap call to every function that can raise a warning. A lot of repetitive code. But you gain very detailed exceptions.

  2. Let you application as a whole to intercept all the warnings and convert them to exceptions. In test suit you will have to define one generic error handler and simply throw a generic exception whenever you get a warning. The problem with this solution is that you will only have generic exceptions and you will have to test exception messages in you test to make sure you are getting the correct exception.

Just don't use @ to suppress the warning. It is not a good solution.