How to mock System.Net.Sockets.Socket

In one of my C# projects I wanted to add tests for a class that uses System.Net.Sockets.Socket. The problem was that the class (FTPConnection) depended directly on Socket as shown in the following class diagram. So I had to find a way to get rid of this direct dependency and mock the Socket class to be able to test FTPConnection without connecting to a live FTP server for each test.

Direct dependency between FTPConnection and System.Net.Sockets.Socket

The problem with mocking System.Net.Sockets.Socket is that it implements no abstract interface and is also sealed (which means you cannot derive from the class). Therefore, you cannot mock the class directly with RhinoMocks (which otherwise would be able to mock the class directly without the need for an interface). So we have a (framework) class to whose source code we have no access (which we would need to add something like Socket : ISocket) and from wich we cannot derive a new class. How do we mock such a seemingly isolated class?

First of all, we need a common interface that we can use for mocking. The problem is that we have to make sure Socket implements this interface (let’s call it ISocket). How do we do that? We find a possible answer to that question in the GoF design patterns catalog:

The adapter design pattern (often referred to as the wrapper pattern or simply a wrapper) translates one interface for a class into a compatible interface. (Wikipedia)

So we have to create an adapter class that implements ISocket and simply delegates all calls to its methods to an instance of Socket. Then we make sure FTPConnection uses the adapter class (or rather ISocket) instead of Socket directly and provide a constructor through which we can inject our own implementation of ISocket (e.g. the mocked one) as shown in the following class diagram.

Mocked System.Net.Sockets.Socket

It is quite a bit of effort to mock the Socket class (you have to define every needed method in ISocket and implement the delegation in SocketAdapter) but it definitely pays off! The resulting design is less coupled due to FTPConnection depending on ISocket instead of Socket directly and can be tested easily by providing a mocked socket that simulates valid or invalid FTP server responses. Examples of how to simulate FTP calls and responses using RhinoMocks are included in my example project below.

Example project in C#

I have created a small console application in C# according to the second class diagram above which demonstrates the mocking of System.Net.Sockets.Socket and produces the output shown in the following screenshot.

Console output of MockASocket

You can download the project here:

Über uns Stefan

Polyglot Clean Code Developer

Ein Kommentar

  1. Thanks thanks thanks! I’ve been struggling with the massive size of my SimpleSocket and SimpleListener test suites for a long time, mainly because I had to have fully implemented Sockets and TcpListeners along with all the threading and synchronization concerns that come along with them. I didn’t know anything about using Callbacks with mock objects, and I never would have thought about using such a simple Adaptor for the socket. Thanks again!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax