Reputation: 67745
Greetings Stackoverflowers,
I have an application in which a communication abstraction layer exists. Each implementation in this layer, called a connector, provides my application with a way of exchanging data with a connected peer (e.g.: through HTTP, TCP sockets, UDP sockets, etc.).
Per example, I have a Connector_Tcp
class that implements methods such as read, write, open and close.
I need to write a unit test for that class. I know that unit tests should have as less dependencies as possible. Unfortunately, in that case, the dependency is a system resource: a socket; and I cannot bypass it.
I need some advice on how to go about unit testing this class.
In my opinion, even though this class is using a system resource, it should be tested as all the other connectors to make sure that it respects the standard established by my application.
I am concerned about such things as binding collisions (Address already in use errors) and blocking. I don't want the unit test to fail because the port is already in use by a system service that has nothing to do with my application.
I have done a lot of unit tests in my days, but none of which relies on such a low-level resource that are sockets.
How would you go about unit testing a socket-dependent class? Open a socket for every unit? Use a single server class, then a manually-defined socket resource to connect to it and test it...?
I guess my problem really is the following:
If the unit test fails... how do I know if:
I need the unit test to test only if the method has been behaving properly or not...
Upvotes: 10
Views: 5669
Reputation: 7083
I've written a similar abstraction layer, albeit in C/C++, and I have had occasion to unit-test the socket based code. I don't know if there's anything inherently specific to PHP here, so I'll just offer what generic advice I can.
Upvotes: 5
Reputation: 17457
I hope I'm understanding your question properly ... if not, please let me know. But what I would do is mock the socket. That would let you write a series of unit tests that ensure that your method does all the right things in various cases.
For example, you could write one unit test that tells the socket mock instance to throw a "port not available" exception. In that case, you could assert that your method caught the exception and logged it with the same text that was in the exception.
And even more central to the issue, you could write a unit test that tells the socket mock instance to return a valid stream of bytes from read(), and then you could assert that your method does the right thing(s) with those bytes.
So you're not actually testing the socket. You're setting up the socket to simulate certain occurrences, and you're testing to see if your code that works with the socket is doing the right things.
(I've used mocking frameworks in Java, C#, Ruby and JavaScript. I've never worked with PHP, but I bet there are some good mocking frameworks out there for it).
EDIT: Yes, there are some mocking frameworks for PHP out there. I can't recommend one, but here are a couple I was able to find: PHPUnit and LastCraft
Upvotes: 2