Это не модульный тест, если он слушает сокет.
Оберните клиента тонким слоем и вместо этого работайте с макетом. Таким образом, вы можете подделать все полученные данные, которые вы хотите.
например. Насмешка над розеткой (упрощенный пример):
Создайте интерфейс ISocket со всеми необходимыми вам методами:
public interface ISocket
{
ISocket Accept( int port );
byte[] Receive( int numberOfBytes );
bool Send( byte[] data );
void Disconnect();
bool Connect( string address, int port );
}
Теперь создайте конкретный класс TcpSocket, реализующий ISocket:
public class TcpSocket : ISocket
{
private Socket socket;
public TcpSocket()
{
socket = new Socket( AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp );
}
// implement all methods of ISocket by delegating to the internal socket
}
Везде, где вы обычно используете System.Net.Sockets.Socket, вместо этого передайте ISocket. Когда вам нужно обновить Socket, используйте TcpSocket. Если вы создаете сокеты в глубине своей системы, вы можете захотеть создать фабрику вместо того, чтобы обновлять TcpSocket напрямую. В процессе тестирования вы можете пройти другую реализацию ISocket (Mock) (возможно, созданную на заводе). Вы можете реализовать свой собственный макет, создав вторую реализацию ISocket под названием MockSocket, которая возвращает тестовые данные в Receive, или вы можете использовать это на бесчисленных модельных фреймворках, чтобы сделать это за вас.
public class MockSocket : ISocket
{
private byte[] testData;
public void SetTestData(byte[] data)
{
testData = data;
}
public byte[] Receive(int numberOfBytes)
{
return testData;
}
// you need to implement all members of ISocket ofcourse...
}
Это может показаться большим усилием, но во всех системах, кроме игрушек, граничный интерфейс API должен быть скрыт за тонким слоем не только для тестирования, но и для обеспечения гибкости. Если, например, вы хотите использовать более мощную библиотеку сокетов вместо System.Net.Socket, вы можете заставить TcpSocket использовать ее без необходимости менять каждое использование сокетов в вашем собственном коде. Это также причина, почему программирование на интерфейс вместо программирования на конкретную реализацию обычно является хорошей идеей: вы можете легко переключать реализации (но это не значит, что вы должны создавать интерфейсы для ВСЕХ ваших классов). Если это все сбивает с толку, читайте больше о насмешках (как здесь: http://en.wikipedia.org/wiki/Mock_object)