我的n00b服务器的一部分:

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);

现在,我想为此代码段编写单元测试。我想伪造一个客户端连接,传递任意数据并检查服务器如何处理它。

我应该如何在C#中做到这一点?

编辑:
我想模拟的是连接本身-我想避免网络连接。

最佳答案

它是否正在监听套接字不是单元测试。
用一个较薄的层包装客户机,然后使用模拟程序。这样,您可以伪造所有想要的接收数据。

例如。模拟套接字(简化示例):

使用所需的所有方法创建接口(interface)ISocket:

public interface ISocket
{
    ISocket Accept( int port );
    byte[] Receive( int numberOfBytes );
    bool Send( byte[] data );
    void Disconnect();
    bool Connect( string address, int port );
}

现在创建一个实现ISocket的具体类TcpSocket:
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来代替。当您需要新建一个套接字时,请使用TcpSocket。如果您在系统内部深处创建套接字,则可能需要创建工厂而不是直接更新TcpSocket。在测试下,您可以传递ISocket的其他实现(模拟)(可能是通过工厂创建的)。您可以通过创建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使用它,而无需在自己的代码中更改套接字的每次使用。这也是为什么对接口(interface)进行编程而不是对具体实现进行编程通常是一个好主意的原因:您可以轻松地切换实现(但这并不意味着您应该为所有类创建接口(interface))。如果这一切使您感到困惑,那么您会读到更多关于 mock 的信息(例如:http://en.wikipedia.org/wiki/Mock_object)

关于c# - 在C#中伪造TCP请求,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9999341/

10-09 09:46