Part of my n00b server:
TcpClient client = tcpListener.AcceptTcpClient();
Thread clientThread = new Thread(new ParameterizedThreadStart(handleClientRegistration));
clientThread.Start(client);
...
//and in the clientThread we wait for data
bytesRead = clientStream.Read(message, 0, 4096);
Now I’d like to write unit tests for this snippet. I want to fake a client connection, pass arbitrary data and check how the server handles it.
How should I do it in C#?
edit:
What I’d like to mock is the connection itself – I want to avoid network connections.
It is not a unit test if it is listening to a socket.
Wrap the client and with a thin layer and work with a mock instead. This way you can fake all the received data you want.
E.g. Mocking the socket (simplified example):
Create an interface ISocket with all the methods you need:
Now create a concrete class TcpSocket implementing ISocket:
Wherever you would normally use a System.Net.Sockets.Socket, pass a ISocket instead. When you need to new up a Socket use TcpSocket. If you create sockets deep down in the guts of your system you might want to create a factory instead of newing up a TcpSocket directly. Under test you can then pass a different implementation of ISocket (the Mock) (possibly created through the factory). You could implement your own mock by creating a second implementation of ISocket called MockSocket which returns test data in Receive or you could use on of the countless mock frameworks to do that for you.
This might seen like a lot of effort, but in all but toy systems the boundary api should be hidden behind a thin layer not only for testing but also to stay flexible. If, for instance, you want to use a more powerful socket library instead of System.Net.Socket you can make TcpSocket use that without the need to change every use of sockets in your own code. This is also the reason why programming to an interface instead of programming to a concrete implementation is usually a good idea: you can easily switch implementations (but that doesn’t mean you should create interfaces to ALL your classes). If this all confuses you read more about mocking (like here: http://en.wikipedia.org/wiki/Mock_object)