2009-03-29 14 views
6

Supongamos que tengo una interfaz con los métodos 'storeData (clave, datos)' y 'getData (clave)'. ¿Cómo debo probar una implementación concreta? ¿Debo verificar si los datos se establecieron correctamente en el medio de almacenamiento (por ejemplo, una base de datos sql) o debería simplemente verificar si devuelve los datos correctos utilizando getData?unidad de almacenamiento de datos de prueba

Si busco los datos en la base de datos, siento que también estoy probando las partes internas del método, pero solo comprobando si devuelve la misma información se siente incompleta.

Respuesta

0

Creo que depende de lo que ocurra con los datos más adelante. Si solo va a acceder a los datos usando storeData y getData, ¿por qué no probar los métodos en concierto? Supongo que hay una posibilidad de que un error se levantarán, y que va a ser un poco más difícil de averiguar si está en storeData o getData, pero me gustaría tener en cuenta que un riesgo aceptable si

  1. hace su prueba más fácil de implementar y
  2. oculta las partes internas, como usted dice

Si los datos se leen de, o insertados en la base de datos utilizando algún otro mecanismo, entonces me gustaría comprobar la base de datos utilizando SQL como sugieres.

@brendan hace una buena observación: cualquiera que sea el método que elija, estará insertando datos en la base de datos. Es una buena idea borrar los datos antes y después de las pruebas para garantizar que pueda lograr resultados consistentes.

1

En casos como este usualmente crearé métodos SetUp y TearDown que disparan antes/después de mis pruebas unitarias. Estos métodos configurarán los datos de prueba que necesito en el archivo db y eliminarán los datos de prueba cuando haya terminado. Pseudo código de ejemplo:

Const KEY1 = "somekey" 
Const VALUE1= "somevalue" 


Const KEY2 = "somekey2" 
Const VALUE2= "somevalue2" 



Sub SetUpUnitTests() 
{ 
    Insert Into SQLTable(KEY1,VALUE1) 
} 


//this test is not dependent on the setData Method 
Sub GetDataTest() 
{ 
    Assert.IsEqual(getData(KEY1),VALUE1) 
} 

//this test is not dependent on getData Method 
Sub SetDataTest() 
{ 
    storeData(newKey,NewData) 
    Assert.IsNotNull(Direct Call to SQL [Select data from table where key=KEY2]) 

} 

Sub TearDownUnitTests() 
{ 
    Delete From table Where key in (KEY1, KEY2) 
} 
2

usted parece estar atrapado en el bombo de las pruebas unitarias, lo que va a hacer es en realidad una prueba de integración. Establecer y obtener el mismo valor de la misma clave es una prueba de unidad que haría con una implementación simulada del motor de almacenamiento, pero en realidad probar el almacenamiento real, digamos su base de datos, como debería, que ya no es una prueba de unidad , pero es una parte fundamental de las pruebas, y me parece una prueba de integración. No use las pruebas unitarias como su martillo , elija las herramientas adecuadas para el trabajo correcto. Divide tus pruebas en más capas.

0

Probar ambos en concierto es una técnica común (al menos, en mi experiencia), y no me rehúso a hacerlo. He utilizado este mismo patrón para serializar/deserializar y analizar e imprimir.

Si no desea acceder a la base de datos, puede utilizar una simulación de base de datos. Algunas personas tienen los mismos sentimientos que usted cuando usa burlas; en parte, es específico de la implementación. Como en todas las cosas, es una solución de compromiso: considere los beneficios de la burla (más rápido, no dependiente de DB) frente a sus inconvenientes (no detectará problemas de DB reales, más lentos).

2

Lo que quiere hacer en una prueba unitaria es asegurarse de que el método hace el trabajo que se supone que debe hacer. Si el método usa dependencias para realizar su trabajo, se burlaría de esas dependencias y se aseguraría de que su método invoque los métodos en los objetos de los que depende con los argumentos apropiados. De esta manera, prueba tu código de forma aislada.

Uno de los beneficios de esto es que impulsará el diseño de su código en una mejor dirección. Para usar el burlarse, por ejemplo, usted gravita naturalmente hacia un código más desacoplado usando la inyección de dependencia.Esto le da la capacidad de sustituir fácilmente sus objetos simulados por los objetos reales de los que depende su clase. También terminas implementando interfaces, que se burlan más naturalmente. Ambas cosas son buenos patrones de diseño y mejorarán tu código.

Para probar su ejemplo particular, por ejemplo, puede hacer que su clase dependa de una fábrica para crear conexiones a la base de datos y un constructor para construir comandos SQL parametrizados que se ejecutan a través de la conexión. Pasaría estas versiones falsas de estos objetos a su clase y se aseguraría de que se invocaron los métodos correctos para configurar la conexión y el comando, construir el comando correcto, ejecutarlo y cortar la conexión. O tal vez, usted inyecta una conexión ya abierta y simplemente crea el comando e invoca. El punto es que su clase está construida contra una interfaz o un conjunto de interfaces, y utiliza burlas para suministrar objetos que implementan esas interfaces y puede registrar invocaciones y proporcionar valores de retorno correctos a los métodos que espera usar de la (s) interfaz (es).