在C#中伪造TCP请求

本文关键字:TCP 请求 伪造 | 更新日期: 2023-09-27 18:29:49

我的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#中做到这一点?

编辑:
我想嘲笑的是连接本身——我想避免网络连接。

在C#中伪造TCP请求

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

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

使用您需要的所有方法创建一个接口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。当您需要新建一个Socket时,请使用TcpSocket。如果您在系统的内部深处创建套接字,您可能希望创建一个工厂,而不是直接新建TcpSocket。在测试中,您可以传递ISocket(Mock)的不同实现(可能是通过工厂创建的)。您可以通过创建名为MockSocket的ISocket的第二个实现来实现自己的mock,该实现在Receive中返回测试数据,也可以使用无数mock框架中的一个来为您实现这一点。

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)

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

此外,不要为每个客户端启动新的Thread,而是使用Task或类似的方法。

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