2009-09-28 18 views
6

Estoy escribiendo un conjunto de pruebas unitarias para probar una biblioteca de comunicación TCP/IP.¿Cómo se maneja la excepción en un hilo de fondo en una prueba unitaria?

Como estoy utilizando BeginAcceptClient y EndAcceptClient, los mensajes se reciben en una cadena de fondo.

Después de recibir un mensaje, realizo algunas afirmaciones sobre él, pero si falla alguna afirmación, el VSTestHost.exe se bloquea.

Busqué en Google un poco y descubrí que las excepciones de Assert se están lanzando en una cadena de fondo.

EDIT: Un código de ejemplo de lo que estoy haciendo, sólo para ilustrar:


public void TestFooMessage() { 
    Server.OnReceive += (s, e) => { 
     Assert.IsInstanceOfType(e.Message, typeof(Foo)); 
    }; 

    var message = new Foo(); 
    Client.Send(message); 
} 

¿Alguien sabe cómo hacer que funcione como se esperaba: Entrar la afirmación y continúa funcionando con normalidad?

Respuesta

6

No se debe escribir la Afirma en el hilo de fondo (por ejemplo: el controlador de eventos de fondo), porque el marco de prueba no puede manejar esto. Solo debes reunir valores allí. Puede sincronizar el hilo principal, por ejemplo, usando AutoResetEvents. Escribe los valores en los campos, afirma los campos en el hilo principal.

Si los mensajes nunca llegan, necesita un tiempo de espera.

Un código de pseudo poco (en realidad no es que pseudo):

private AutoResetEvent ReceiveEvent = new AutoResetEvent(false); 
private EventArgs args; 
private bool ReceiveCalled = false; 

// event handler with some argument 
private void Receive(object sender, EventArgs args) 
{ 
    // get some arguments from the system under test 
    this.args= args; 

    // set the boolean that the message came in 
    ReceiveCalled = true; 

    // let the main thread proceed 
    ReceiveEvent.Set(); 
} 

[TestMethod] 
public void Test() 
{ 
    // register handler 
    Server.OnReceive += Receive; 

    var message = new Foo(); 
    Client.Send(message); 

    // wait one second for the messages to come in 
    ReceiveEvent.WaitOne(1000); 

    // check if the message has been received 
    Assert.IsTrue(
    ReceiveCalled, 
    "AcceptClientReceived has not been called"); 

    // assert values from the message 
    Assert.IsInstanceOfType(args.Message, typeof(Foo))  
} 

Por cierto: aún se puede escribir el controlador como una expresión lambda e incluso evitar los campos mediante el uso de variables locales. Pero podría ser más difícil de leer si todo está en un solo método.

1

sospecho que usted necesita básicamente una especie de "todo bien" bandera:

  1. crear este indicador global, y la ponemos a true en el inicio de la prueba
  2. Escribir un método paralelo Assert que borra la bandera y tal vez establece otra variable para el "motivo" (o la agrega a una lista) luego sale del hilo limpiamente (si es posible)
  3. Haga que el hilo principal de prueba espere a que todos los otros hilos terminen, luego verifique la bandera.

Es posible que algunos marcos de prueba han construido en esta, pero no sé de cualquier improvisada ...

+1

El problema es que los hilos son creados por el sistema bajo prueba. Por lo general, ni siquiera los conoces, a menos que te devuelvan la llamada. No hay una solución general para los hilos de fondo en las pruebas unitarias. –

+1

Espera un evento en la función de prueba y configura el evento en la devolución de llamada asíncrona. –

0

He intentado lo que sugiere Stefan y las siguientes obras para mí:

public void TestFooMessage() { 
    Foo message = null; 
    var resetEvent = new AutoResetEvent(false); 

    Server.OnReceive += (s, e) => { 
     message = e.Message; 
     resetEvent.Set(); 
    }; 

    var message = new Foo(); 
    Client.Send(message); 

    if (resetEvent.WaitOne(1000)) { 
     Assert.IsInstanceOfType(e.Message, typeof(Foo)); 
    } else { 
     Assert.Fail("Foo not received!"); 
    } 
} 

Gracias!

Cuestiones relacionadas