2012-04-03 34 views
9

Một phần của máy chủ n00b tôi:yêu cầu giả mạo TCP trong C#

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

Bây giờ tôi muốn viết bài kiểm tra đơn vị cho đoạn này. Tôi muốn giả mạo một kết nối máy khách, truyền dữ liệu tùy ý và kiểm tra xem máy chủ xử lý nó như thế nào.

Tôi nên làm như thế nào trong C#?

chỉnh sửa:
Điều tôi muốn giả lập chính là kết nối - Tôi muốn tránh kết nối mạng.

+0

Tôi nghĩ bạn phải thực sự kết nối trên ổ cắm ...? Có lẽ tôi đang thiếu câu hỏi của bạn, nhưng chỉ cần mở một ổ cắm khác, gọi kết nối, và gửi một số dữ liệu ...? – Aerik

+0

Đây chính xác là câu hỏi này là gì: tôi có nên mở ổ cắm hay tôi nên thử toàn bộ giao diện TCP. Tôi nghĩ rằng một thử nghiệm thích hợp không nên sử dụng một nguồn lực hạn chế như giao diện mạng .. hoặc tôi sai. – emesx

Trả lời

16

Nó không phải là một bài kiểm tra đơn vị nếu nó đang nghe một ổ cắm. Quấn khách hàng và với một lớp mỏng và làm việc với một mô hình thay thế. Bằng cách này bạn có thể giả mạo tất cả các dữ liệu nhận được mà bạn muốn.

Ví dụ: Mocking ổ cắm (giản thể ví dụ):

Tạo một ISocket giao diện với tất cả các phương pháp bạn cần:

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

Bây giờ tạo ra một lớp TcpSocket bê tông thực hiện 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 
} 

Bất cứ nơi nào bạn bình thường sử dụng một System.Net.Sockets.Socket, vượt qua một ISocket thay thế. Khi bạn cần tạo mới một Socket sử dụng TcpSocket. Nếu bạn tạo các ổ cắm sâu bên trong ruột của hệ thống, bạn có thể muốn tạo một nhà máy thay vì tạo một TcpSocket trực tiếp. Dưới thử nghiệm, bạn có thể vượt qua một thực hiện khác nhau của ISocket (Mock) (có thể được tạo ra thông qua nhà máy). Bạn có thể thực hiện mô hình của riêng bạn bằng cách tạo ra một triển khai thứ hai của ISocket được gọi là MockSocket, nó trả về dữ liệu kiểm tra trong Receive hoặc bạn có thể sử dụng trên vô số các khuôn mẫu giả để làm điều đó cho bạn.

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... 
} 

sức này thấy giống như rất nhiều nỗ lực, nhưng trong tất cả nhưng hệ thống đồ chơi các api ranh giới nên được ẩn đằng sau một lớp mỏng không chỉ để thử nghiệm nhưng cũng ở lại linh hoạt. Nếu, ví dụ, bạn muốn sử dụng một thư viện socket mạnh hơn thay vì System.Net.Socket bạn có thể làm cho TcpSocket sử dụng mà không cần phải thay đổi mọi cách sử dụng các socket trong mã của riêng bạn. Đây cũng là lý do tại sao lập trình cho giao diện thay vì lập trình để triển khai thực hiện cụ thể thường là một ý tưởng hay: bạn có thể dễ dàng chuyển đổi triển khai (nhưng điều đó không có nghĩa là bạn nên tạo giao diện cho TẤT CẢ các lớp của bạn). Nếu tất cả điều này gây nhầm lẫn cho bạn, hãy đọc thêm về chế nhạo (như ở đây: http://en.wikipedia.org/wiki/Mock_object)

+2

đây là cách để đi –

+0

OK. Tôi có một máy chủ TCP - chủ đề, lắng nghe các kết nối TCP. Và tôi có một khách hàng - giao tiếp với máy chủ. Bây giờ tôi đang thử nghiệm máy chủ, vì vậy chính xác những gì tôi nên giả lập .. khách hàng? tại sao .. vì tôi có thể buộc nó gửi bất kỳ dữ liệu nào. Tôi đã suy nghĩ thêm về một C# -way của mocking giao diện TCP do đó không có lưu lượng truy cập được tạo ra vv. Trong phong cách bộ nhớ .. – emesx

+0

Bạn nên thử lớp TcpClient. – EricSchaefer

3

Cách dễ nhất là có phương pháp lấy Stream và thực hiện bất kỳ thao tác nào bạn mong đợi trên đó. Bằng cách đó, bạn có thể chỉ cần chuyển một MemoryStream có dữ liệu bạn muốn vào đó. Điều này sẽ không giúp kiểm tra mã khởi tạo của khách hàng của bạn, nhưng không rõ liệu đó có quan trọng với bạn hay không.

Ngoài ra, không bắt đầu một mới Thread cho mỗi khách hàng, sử dụng Task hoặc phương pháp tương tự để thay thế.

+0

Cảm ơn bạn đã tip! – emesx

2

Để kiểm tra đơn vị này, có thể bạn sẽ cần phải tạo một lớp trừu tượng ở phía trên của .NET TCP API. Kiểm tra đơn vị thường là để kiểm tra đầu vào, đầu ra và tương tác của mã của bạn - không phải để kiểm tra sự tương tác của mã của bạn với các API khác. Đó là vai trò của các bài kiểm tra tích hợp. Lớp trừu tượng bạn sẽ tạo sẽ không được kiểm tra đơn vị, nhưng nó sẽ cho phép bạn dễ dàng hoán đổi nó với một đối tượng giả hoặc giả để kiểm tra phần còn lại của mã của bạn.

Các vấn đề liên quan