2010-02-12 24 views
6

Al probar unidades de una base de código, ¿cuáles son las señales reveladoras de que necesito utilizar objetos falsos?Pruebas unitarias de métodos vacíos/simulacros de señales de objetos burlones

¿Sería esto tan simple como ver muchas llamadas a otros objetos en la base de código?

Además, ¿cómo puedo probar los métodos de prueba que no devuelven valores? Entonces, si un método está volviendo vacío pero imprime en un archivo, ¿acabo de verificar el contenido del archivo?

Burlarse es para dependencias externas, así que eso es literalmente todo, ¿no? Sistema de archivos, base de datos, red, etc. ...

+0

Para su último punto, consulte: http://martinfowler.com/articles/mocksArentStubs.html solo para asegurarse de que conoce las diferencias. – Finglas

+0

He aquí una buena lectura que aborda algunas de estas preguntas: http://xunitpatterns.com/TestStrategy.html –

Respuesta

2

En todo caso, es probable que use más de los simulacros.

Cada vez que una clase llama a otra, generalmente me burlo de esa llamada y verifico que la llamada se realizó con los parámetros correctos. De lo contrario, tendré una prueba unitaria que verifique que el código concreto del objeto burlado se comporte correctamente.

Ejemplo:

[Test] 
public void FooMoo_callsBarBaz_whenXisGreaterThan5() 
{ 
    int TEST_DATA = 6; 
    var bar = new Mock<Bar>(); 
    bar.Setup(x => x.Baz(It.Is<int>(i == TEST_DATA))) 
     .Verifiable(); 

    var foo = new Foo(bar.Object); 

    foo.moo(TEST_DATA); 

    bar.Verify(); 
} 

... 
[Test] 
public void BarBaz_doesSomething_whenCalled() 
{ 
    // another test 
} 

Lo es para mí, si trato de probar un montón de clases como un gran pegote, a continuación, por lo general hay toneladas de código de configuración. No solo es bastante confuso de leer cuando tratas de entender todas las dependencias, es muy frágil cuando hay que hacer cambios.

Prefiero las pequeñas pruebas sucintas. Más fácil de escribir, más fácil de mantener, más fácil de entender el propósito de la prueba.

+4

Terminas la prueba de vinculación a los detalles de la implementación interna con simulaciones que significan que tienden a romperse más a menudo. Con las pruebas basadas en el estado, solo le importa una salida. Los simulacros son generalmente más complicados de configurar, pero ciertamente tienen su lugar en las pruebas unitarias. – Finglas

-1

Las pruebas unitarias son solo para una pieza de código que funciona autónomamente dentro de sí misma. Esto significa que no depende de otros objetos para hacer su trabajo. Debería usar simulaciones si está realizando una programación controlada por prueba o programación de prueba inicial. Usted crearía un simulacro (o talón como me gusta llamarlo) de la función que creará y establecerá ciertas condiciones para que pase la prueba. Originalmente la función devuelve falso y la prueba falla, lo que se espera ... luego escribes el código para hacer el trabajo real hasta que pase.

Pero a lo que creo que se refiere es a las pruebas de integración, no a las pruebas unitarias. En ese caso, debe usar simulaciones si está esperando que otros programadores finalicen su trabajo y actualmente no tiene acceso a las funciones u objetos que están creando. Si conoce la interfaz, que con suerte lo burla no tiene sentido y es una pérdida de tiempo, entonces puede crear una versión simplificada de lo que espera obtener en el futuro.

En resumen, los simulacros se utilizan mejor cuando está esperando a otros y necesita algo allí para terminar su trabajo.

Debería intentar siempre devolver un valor si es posible. A veces se encuentra con problemas donde ya está devolviendo algo, pero en C y C++ puede tener parámetros de salida y luego utilizar el valor de retorno para la comprobación de errores.

+0

-1 - Esto se basa en un malentendido de los simulacros y los talones. Si bien definitivamente obtienes funcionalidad cuando haces TDD, eso no es para lo que son los objetos falsos. No se burla del objeto bajo prueba, se burla de sus dependencias. – TrueWill

+0

Sí, creo que hay una diferencia entre trozos y burlas. Creo que malinterpretaste lo que dije. En el primer párrafo estaba describiendo qué pruebas unitarias eran y cómo podría usar un objeto que creó que simula un objeto real al que actualmente no tiene acceso o no le importa tener acceso. En el segundo párrafo comencé a describir que los simulacros son para pruebas de integración ... pero estaba equivocado. Las pruebas de integración se realizan después de la prueba unitaria y se realizan con objetos reales, no simulacros. De cualquier manera, los simulacros se utilizan mejor cuando quiere hacer pruebas unitarias antes de integrarse. –

0

Mocks/stubs/fakes/test doubles/etc. están bien en pruebas unitarias, y permiten probar la clase/sistema bajo prueba de forma aislada. Las pruebas de integración pueden no usar ningún simulacro; de hecho golpean la base de datos u otra dependencia externa.

Utiliza un simulacro o un talón cuando sea necesario. En general, esto se debe a que la clase que intentas probar depende de una interfaz. Para TDD, usted desea programar interfaces, no implementaciones, y usar inyección de dependencia (generalmente hablando).

Un caso muy simple:

public class ClassToTest 
{ 
    public ClassToTest(IDependency dependency) 
    { 
     _dependency = dependency; 
    } 

    public bool MethodToTest() 
    { 
     return _dependency.DoSomething(); 
    } 
} 

IDependency es una interfaz, posiblemente, uno con llamadas costosas (acceso de base de datos, llamadas de servicio web, etc.). Un método de prueba puede contener código similar a:

// Arrange 

var mock = new Mock<IDependency>(); 

mock.Setup(x => x.DoSomething()).Returns(true); 

var systemUnderTest = new ClassToTest(mock.Object); 

// Act 

bool result = systemUnderTest.MethodToTest(); 

// Assert 

Assert.That(result, Is.True); 

Tenga en cuenta que estoy haciendo pruebas de estado (como se sugiere @Finglas), y yo sólo estoy afirmando en contra del sistema bajo prueba (la instancia de la clase I' m prueba). Puedo verificar los valores de propiedad (estado) o el valor de retorno de un método, como se muestra en este caso.

Recomiendo leer The Art of Unit Testing, especialmente si usa .NET.

Cuestiones relacionadas