2012-04-03 12 views
9

parte de mi servidor de n00b:Falsificación de solicitudes PCT en 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); 

Ahora me gustaría escribir pruebas unitarias para este fragmento. Quiero falsificar una conexión con el cliente, pasar datos arbitrarios y verificar cómo lo maneja el servidor.

¿Cómo debo hacerlo en C#?

editar:
Lo que me gustaría burlar es la conexión en sí: quiero evitar las conexiones de red.

+0

Creo que realmente tiene que conectarse en el zócalo ...? Tal vez me falta su pregunta, ¿pero solo abra otro socket, llame a connect y envíe datos ...? – Aerik

+0

Esto es exactamente de lo que se trata esta pregunta: ¿Debería abrir sockets o debería burlarme de toda la interfaz TCP? Creo que una prueba adecuada no debería usar un recurso limitado como la interfaz de red ... ¿o estoy equivocado? – emesx

Respuesta

16

No es una prueba unitaria si está escuchando una toma de corriente. Envuelva al cliente y con una capa delgada y trabaje con un simulacro en su lugar. De esta manera puede falsificar todos los datos recibidos que desee.

E.g. Burlándose de la toma (ejemplo simplificado):

Crear una iSocket interfaz con todos los métodos que necesita:

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

Ahora cree un TcpSocket clase concreta implementació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 
} 

Siempre que lo haría normalmente use un System.Net.Sockets.Socket, pase un ISocket en su lugar. Cuando necesite actualizar un Socket, use TcpSocket. Si crea tomas en las entrañas de su sistema, es posible que desee crear una fábrica en lugar de renovar un TcpSocket directamente. En prueba, puede pasar una implementación diferente de ISocket (el simulacro) (posiblemente creado a través de la fábrica). Podrías implementar tu propio simulacro creando una segunda implementación de ISocket llamada MockSocket que devuelve datos de prueba en Recibir o podrías usar uno de los innumerables frameworks simulados para hacer eso por ti.

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

Esto podría verse como un montón de esfuerzo, pero en todo menos en los sistemas de juguete de la API límite debe estar oculto detrás de una capa delgada, no sólo para la prueba sino también para mantenerse flexible. Si, por ejemplo, desea utilizar una biblioteca de socket más poderosa en lugar de System.Net.Socket, puede hacer que TcpSocket lo use sin la necesidad de cambiar cada uso de sockets en su propio código. Esta es también la razón por la que programar una interfaz en lugar de programar para una implementación concreta suele ser una buena idea: puede cambiar fácilmente las implementaciones (pero eso no significa que deba crear interfaces para TODAS sus clases). Si todo esto le confunde, lea más acerca de la burla (como aquí: http://en.wikipedia.org/wiki/Mock_object)

+2

este es el camino a seguir –

+0

Bien. Tengo un servidor TCP: hilos, escuchando conexiones tcp. Y tengo un cliente, comunicándome con el servidor. Ahora estoy probando el servidor, ¿de qué me debería burlar exactamente ... el cliente? por qué ... ya que puedo obligarlo a enviar cualquier información de cualquier forma. Estaba pensando más en una forma C# de burlarse de las interfaces TCP para que no se genere tráfico, etc. Más estilo en memoria ... – emesx

+0

Debería burlarse de la clase TcpClient. – EricSchaefer

3

La manera más fácil sería tener un método que lleva un Stream y realiza las operaciones que espera en él. De esta forma, puede pasar un MemoryStream que tiene los datos que desea. Esto no ayudará a probar el código de inicialización de su cliente, pero no estaba claro si eso era importante para usted o no.

Además, no comience un nuevo Thread por cliente, use Task o una metodología similar en su lugar.

+0

¡Gracias por el consejo! – emesx

2

Para probar la unidad de este modo, es probable que necesite crear una capa de abstracción sobre .NET TCP API. Las pruebas unitarias suelen ser para probar las entradas, salidas e interacción de su código, no para probar la interacción de su código con otras API. Ese es el papel de las pruebas de integración. La capa de abstracción que creará no se probará en unidades, pero le permitirá cambiarla fácilmente con un objeto falso o falso para probar el resto de su código.

Cuestiones relacionadas