C# 在C中伪造TCP请求#

C# 在C中伪造TCP请求#,c#,.net,unit-testing,networking,mocking,C#,.net,Unit Testing,Networking,Mocking,n00b服务器的一部分: TcpClient client = tcpListener.AcceptTcpClient(); Thread clientThread = new Thread(new ParameterizedThreadStart(handleClientRegistration)); clientThread.Start(client); ... //and in the clientThread we wait for data bytesRead = clientStre

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#中完成它

编辑:

我想模拟的是连接本身——我想避免网络连接。

如果它正在侦听套接字,则不是单元测试。 用薄层包装客户机和,并使用模拟层。这样你就可以伪造你想要的所有接收到的数据

例如模拟插座(简化示例):

使用所需的所有方法创建接口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。当您需要新建一个套接字时,请使用TcpSocket。如果在系统的内部深处创建套接字,您可能希望创建一个工厂,而不是直接创建一个TcpSocket。在测试中,您可以通过不同的ISocket实现(模拟)(可能是通过工厂创建的)。您可以通过创建名为MockSocket的第二个ISocket实现来实现自己的模拟,该实现在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使用它,而无需更改自己代码中套接字的每次使用。这也是为什么编程到接口而不是编程到具体实现通常是个好主意的原因:您可以轻松切换实现(但这并不意味着您应该为所有类创建接口)。如果这些都让你感到困惑,你会读到更多关于模拟的内容(比如这里:)

最简单的方法就是有一个方法,它接受一个
流,并执行你所期望的任何操作。这样,您只需传递一个包含所需数据的
MemoryStream
。这无助于测试客户端初始化代码,但不清楚这对您是否重要


另外,不要为每个客户端启动一个新的
线程
,而是使用
任务
或类似的方法。

为了进行单元测试,您可能需要在.NET TCP API之上创建一个抽象层。单元测试通常用于测试代码的输入、输出和交互,而不是测试代码与其他API的交互。这就是集成测试的作用。您将创建的抽象层不会进行单元测试,但它将允许您轻松地用假对象或模拟对象替换它,以便测试其余代码。

我认为您必须真正连接套接字。。。?也许我遗漏了你的问题,但只需打开另一个套接字,调用connect,然后发送一些数据…?这正是这个问题的核心:我应该打开套接字,还是模拟整个TCP接口。我认为一个合适的测试不应该使用有限的资源,比如网络接口。。还是我错了,好吧。我有一个TCP服务器线程,监听TCP连接。我有一个客户端-与服务器通信。现在我正在测试服务器,那么我到底应该嘲笑什么。。客户?为什么?因为我可以强迫它以任何方式发送任何数据。我在考虑更多的模拟TCP接口的C#方式,这样就不会产生流量等。更多的是内存风格。你应该模拟TcpClient类。让它做什么呢?因为我有这个类的源代码,它向它的方法发送任何传递的数据。让它返回测试数据?我可以不用模拟就可以做到这一点。我可以模拟/重定向网络连接到c#中的本地内存流吗?