2011-11-22 22 views
7

Quiero probar un fragmento de código que devuelve un objeto.Pruebas unitarias ... cómo mejorarlo

utilizo NUnit y en una clase de prueba, escribo un método para probar si mi método funciona bien ...

[Test] 
public void GetMyObjectFromLog() 
{ 
    string _xmlFilePath = @"C:\XmlFile.xml"; 
    MyObjectParser _myObjectParser = new MyObjectParser(); 
    MyObject _mockMyObject = new MyObject 
           { 
            Title = "obj", 
            Name = "objName" 
           } 
    MyObject _myObject = _myObjectParser.GetMyObjectFromLog(_xmlFilePath); 

    Assert.AreEqual(_mockMyObject , _myObject); 
} 

Esta prueba no funciona porque MyObject no altera temporalmente Equals método, y don No desea sobrescribir el método Equals solo para fines de prueba.

Así que volver a escribir la prueba como esta:

[Test] 
public void GetMyObjectFromLog() 
{ 
    string _xmlFilePath = @"C:\XmlFile.xml"; 
    MyObjectParser _myObjectParser = new MyObjectParser(); 
    MyObject _myObject = _myObjectParser.GetMyObjectFromLog(_xmlFilePath); 

    Assert.AreEqual("obj", _myObject.Title); 
    Assert.AreEqual("objName", _myObject.Name); 
} 

Ok, funciona ... pero es este examen es pertinente? Además, hay una dependencia de un archivo.

¿Es pertinente utilizar un marco simulado en lugar de? Y cómo usarlo ?

¡Gracias!

+0

En realidad se comarison podría escribirse en una sola línea, pero tiene mala legibilidad: 'Assert.That (myObjectA, Is.EqualTo (myObjectB) .Using ((x, y) => x.Name == y .Name && x.Title == y.Title? 0: 1)); ' – Restuta

Respuesta

1

es absolutamente correcto tener una referencia a un archivo. En general, hay dos tipos de tipos de prueba: pruebas unitarias y pruebas de integración.

Las pruebas de integración siempre interactúan con algún archivo/base de datos o lo que sea. En su caso, podría mejorar la prueba burlándose de _myObjectParser.GetMyObjectFromLog.

Puede escribir el simulacro usted mismo o utilizar un marco como rhinomocks. Un libro muy bueno para nunit/rhinomocks es: The Art of Unit Testing.

una versión mejor comprobable de GetMyObjectFromLog podría tener este aspecto:

public MyObject GetMyObjectFromLog(IMyXmlReader reader) 
{ 
    var xmlData = reader.GetData(); 
    //make your object here 
    var obj = new MyObject(xmlData); 
    return obj; 
} 

A continuación, puede aplicar 2 nuevas clases que implemments un IMyXmlReader interfaz, que se lee de un archivo para su código productiva, y uno que devuelve solo siempre la misma cadena en GetData().

Puede utilizar su clase que devuelve siempre una cadena estática para las pruebas de su unidad.

¿Entiendes? Lo siento por mi inglés :)

+1

Jesus ... por qué debería agregar soluciones al desbordamiento de la pila si alguien siempre la derriba. No me gusta eso – Grrbrr404

+0

Lol. Él también me votó a mí. Intentas ayudar y eso es lo que obtienes :) –

+0

Y la pregunta obtienes 3 votos jaja. –

1

Sí, se ve bien así. Sin embargo, puede anular Equals en su proyecto de prueba, si no lo necesita en su proyecto principal. P.ej. generalmente creo clases que promueven las clases privadas y protegidas a las públicas. Por lo tanto, puede extender su proyecto principal para simplemente probar en su proyecto de prueba.

La dependencia de un archivo está bien, simplemente ponga este archivo en su proyecto de suite de pruebas.

0

El propósito de las pruebas unitarias es poner a prueba la lógica del código, la prueba anterior está haciendo dos cosas: 1. Logic 2. Buscar

dije búsqueda ya que están tratando de igualar un objeto que creaste en un archivo externo. Si lo haces, el problema es que tu compilación comenzará a fallar si no hay un archivo externo presente y no quieres eso.

Solución: Cree el archivo sobre la marcha pero no cree un archivo físico, cree un archivo en la memoria y luego inserte el objeto que necesita para hacer coincidir, luego haga coincidir el objeto.

De esta manera, esta prueba nunca se romperá.

+0

¿Por qué votaste esto? –

+1

No descarté esto, pero su respuesta no tiene sentido; no puede crear un archivo en la memoria. El archivo es una clase estática. ¿Te refieres a Stream? –

2

Sobre esa dependencia en el archivo (que incluso no parece ser en el proyecto!):

Se podría anular que _myObjectParser.GetMyObjectFromLog aceptar también un arroyo. Luego puede agregar ese archivo XML como recurso incrustado y leerlo desde el ensamblado.

5

En primer lugar, el método dentro del analizador debe ser el nombre "Parse" en lugar de "Obtener".

En segundo lugar, si no desea que el objeto en sí se pueda comparar con otro, entonces está perfectamente bien compararlos tal como lo hizo (propiedad por propiedad). Pero esto se puede extraer en un método auxiliar en la clase de prueba.

Y, por último, realmente no desea ajustar el parseador con un archivo. Solo quieres analizar el texto. Si desea incluir un método de ayuda estático que también abre un archivo y todo, esa es su elección, pero no debe ser una dependencia de instancia pura.

[Test] 
public void ParsesObjectFromXml() 
{ 
    string xmlInput = " ... "; 
    MyObjectXmlParser parser = new MyObjectXmlParser(); 
    MyObject expected = new MyObject() {Title = "obj", Name="objName"}; 

    AssertMyObjectsAreEqual(expected, parser.Parse(xmlInput)); 
} 

private bool AssertMyObjectsAreEqual(MyObject expected, MyObject actual) 
{ 
    Assert.AreEqual(expected.Title, actual.Title); 
    Assert.AreEqual(expected.Name, actual.Name); 
} 

Ahora, tanto su clase y su prueba son más claras y sólo tienen una sola responsabilidad.