问题
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