Most mocking framework know how to mock an interface or (abstract) class and fake the method calls that are performed on these mocks. However, hardly any of them can do anything other than provide a return value when the mock method is called.
This poses a serious problem when ref or out parameters are provided or when reference types are used that need to be manipulated as part of the mock method. Here’s a scenario in which I needed to do exactly that.
The System.Net.Sockets.Socket class can send and receive raw data through a byte buffer. Take a look at some of the signatures for the Socket::Send method:
When the Receive method is called, a byte buffer or list of ArraySegments of byte buffers is passed. The return value of Receive will indicate the actual number of bytes that were received. But, … more importantly, the buffer now contains the bytes read from the socket. How would you go about mocking this?
At a first impression you could think that you would create a wrapper or abstraction of the Socket, give it an interface and mock it from there. True, but this still leaves you with a new class to test. If you strive for a high code coverage, or want to do an integration test up until the Socket level, then this offers no way out.
Enter stage for TypeMock. Using this mocking framework you can handle method calls on mocked objects and have dynamic return values. The key to this all is the DynamicReturnValue class. I wrote this extension method for the Socket class. This extension method prepares a mocked Socket object to fake reception of network data. This data is provided in a packet (an ArraySegment of byte). From this packet the data is read and transferred to the buffer that is passed to the Receive method when it is called later on.
In this method I expect that the extended Socket object is a mocked object. I arrange the mock to expect and return a DynamicReturnValue for the Receive method. The constructor for the DynamicReturnValue takes a delegate that is called instead of the Receive method on the mocked object. The constructor takes two parameters. The most important one is the object parameters, that holds the parameters/arguments of the method called (Receive in our case).
The ExpectAndReturn method does not know which overload of Receive is called. You should have enough control over the situation to know which one it is. The FakeReceive method assumes that the overloads are either of these:
For the first overload the number of parameters is 1. The entire packet is transferred to the buffer in that case. Otherwise the requested number of bytes is read into the buffer. The provided packet should contain enough bytes. In both cases the number of bytes read is returned.
The next code fragment shows how to use the FakeReceive method in a test fixture.
First, the mock Socket is created. Next, data is loaded from a binary test file. The socket is prepared for three consecutive Receive calls that read more and more from the binary data. Lastly, the GameSpyMaster2Response object is tested by calling the Receive method (not the one from Socket, but of the object under test) passing in the mocked and prepared socket.
Works like a charm. There’s room for improvement, though. You could allow for faking more overloads of Receive. I just called YAGNI and went on.