2011-04-05 13 views
29

Tengo un servicio web que básicamente ejecuta algunos procedimientos almacenados, transforma los datos y los envía al navegador. Ningún mapeador de ORM elegante o algo así involucrado. Para poder escribir la prueba sin acceder a la base de datos, he hecho lo siguiente:Tropezar/burlarse de una base de datos en .Net

  • He extraído todas las llamadas al DB en una clase. Los métodos devuelven solo los objetos DataSet y DataTable.
  • Se ejecutó una llamada de muestra para cada método y se serializó el DataSet/DataTable en el disco.
  • Se extrajo una interfaz que expone todos los métodos disponibles.
  • Implementé una clase de base de datos falsa que simplemente carga los datos serializados y los devuelve.

Ahora tengo resultados de muestra serializados que puedo verificar con mi proyecto, y puedo usar la base de datos falsa en mis pruebas.

Esto funciona bastante bien para mí. ¿Hay algún marco que facilite la creación y carga de los datos de muestra? Mi proyecto actual es pequeño, pero usaría el mismo esquema en proyectos más grandes.

Actualización:

Obviamente todas las respuestas no están mal, pero pierden el punto. Conozco los conceptos básicos de las pruebas unitarias. Pero mi código está funcionando con DataTables, así que de alguna manera tendría que falsificar mis DataTables. Construir una DataTable desde el principio no es una tarea fácil, y podría aumentar mis pruebas y reducir la legibilidad. En mi caso, sería completamente imposible generar datos útiles de muestra a mano.

Por lo tanto, ejecuté algunas llamadas de muestra en una base de datos de muestra para obtener algunos DataTables. He serializado estas tablas en el disco y uso las versiones serializadas para crear mis DataTables falsos durante la prueba. De esa forma, las pruebas son independientes de la base de datos.

Existen diferentes opciones sobre cómo estructurar el código para facilitar la deserialización de las tablas. Pero esos son detalles de implementación que no necesitan discusión en este punto. Mi problema es el siguiente:

Administrar las llamadas de muestra y (de) serializar las tablas es un trabajo tedioso. Estaba buscando algunas herramientas para hacer esto más fácil.

+0

Entonces, ¿qué exactamente están probando sus pruebas? que la clase de db falsa puede devolver datos falsos? o estás probando la transformación? –

+0

Estoy probando la transformación. Esta parte de las pruebas asume que la base de datos está bien y me gustaría probar todo lo que sucede después de obtener el DataSet/DataTable de la base de datos. – Achim

+4

Si está probando solo la transformación, idealmente aislaría el código para eso y escribiría pruebas unitarias estrictamente en ese código. –

Respuesta

5

Para probar la transformación de la unidad, realmente no debería necesitar burlarse de la base de datos. Sospecho que has acoplado estrechamente las transformaciones con tus llamadas a la base de datos. Lo que se quiere hacer aquí es extraer toda la lógica de la transformación en una clase de su propio como el siguiente:

public static Transformations 
{ 
    public static DataSet TransformationA(DataSet dataSet) 
    { 
     //transformation logic here 
    } 

    public static DataSet TransformationB(DataSet dataSet) 
    { 
     //transformation logic here 
    } 
} 

Con esto se puede prueba de unidad sólo la lógica transformaciones mediante introducción de un conjunto de datos y luego afirmando devuelto el conjunto de datos tiene las transformaciones correctas aplicadas. Esto evitará que tenga que implementar otro almacén de datos (su base de datos "falsa") solo con fines de prueba.

Esperemos que esto ayuda

+0

Ver mi actualización de la pregunta. El principal problema no es la transformación, sino la creación de los DataSets/Tables de muestra. – Achim

+0

Creo que Stuartf es completamente correcto. La única razón por la que puedo ver hasta ahora que el problema es 'pero la creación de la muestra DataSets/Tables'. – Dave

2

Se podía burlarse de su clase con DataAccess Rhinomocks y devolver una tabla de datos falsos. Entonces puede probar el código que usa esta DataTable.

var mockedDatatable= GetMockdt(); 

var mocks = new MockRepository(); 
var dal = mocks.StrictMock<DataAccess>(); 

using (mocks.Record()) 
{ 
    Expect.Call(dal.GetDataTableFromDatabase("", null)).Return(mockedDatatable).IgnoreArguments(); 
} 

using (mocks.Playback()) 
{ 
    new SomeClass(dal); 
} 

actualizar el mensaje mockdt

private static DataTable GetMockdt() 
{ 
    var dt = new DataTable(); 

    dt.Columns.Add("pageHeader"); 
    dt.Columns.Add("templatename"); 
    dt.Columns.Add("pageText"); 
    dt.Columns.Add("pageTitleBar"); 
    dt.Columns.Add("metaDescription"); 
    dt.Columns.Add("pageStartCode"); 
    dt.Columns.Add("pageEndCode"); 
    dt.Columns.Add("templateStartCode"); 
    dt.Columns.Add("templateEndCode"); 
    dt.Columns.Add("Author"); 
    dt.Columns.Add("version_date"); 
    dt.Columns.Add("pageurl"); 
    dt.Columns.Add("type"); 
    dt.Columns.Add("isparent"); 
    dt.Columns.Add("pagename"); 
    dt.Columns.Add("parentname"); 
    dt.Columns.Add("url"); 

    var mockRow = dt.NewRow(); 

    mockRow["pageHeader"] = "homepage"; 
    mockRow["pageText"] = "<p>home</p>"; 
    mockRow["templatename"] = "home"; 
    mockRow["pageTitleBar"] = "homepages"; 
    mockRow["metaDescription"] = "homepages"; 
    mockRow["pageStartCode"] = "homepages"; 
    mockRow["pageEndCode"] = "homepages"; 
    mockRow["templateStartCode"] = "homepages"; 
    mockRow["templateEndCode"] = "homepages"; 
    mockRow["Author"] = "someone"; 
    mockRow["version_date"] = ""; 
    mockRow["pageurl"] = "home"; 
    mockRow["type"] = "internal"; 
    mockRow["isparent"] = "true"; 
    mockRow["pagename"] = "homepage"; 
    mockRow["parentname"] = "root"; 
    mockRow["url"] = "homepage"; 

    dt.Rows.Add(mockRow); 

    return dt; 
} 
+0

Consulte la actualización de mis preguntas y las demás respuestas: sé cómo simular un objeto. Me interesa cómo implementar GetMockdt() – Achim

+0

Actualicé la publicación con el mockdt. – Ivo

+0

Si vuelve a leer mi actualización, verá que su solución es exactamente lo que no quiero hacer. La creación de datos de muestra sería mucho trabajo en mi caso. Mi pregunta se dirige exactamente hacia una solución simple para lo que usted propone. – Achim

27

De la lectura de las otras respuestas y varios comentarios que has hecho, parece que quiere una manera más fácil de generar grandes conjuntos de datos de población para las pruebas de integración que no lo hace golpear la base de datos.

NBuilder es una gran biblioteca de código abierto que he logrado crear grandes cantidades de datos de prueba. Simplemente combine NBuilder, algunas clases básicas de objetos POCO, y un poco de reflexión - que tendrá un montón de grandes tablas de datos se pueden combinar fácilmente en conjuntos de datos en poco tiempo:

public class Person 
{ 
    public string First { get; set; } 
    public string Last { get; set; } 
    public DateTime Birthday { get; set; } 
} 

private DataTable GenerateDataTable<T>(int rows) 
{ 
    var datatable = new DataTable(typeof(T).Name); 
    typeof(T).GetProperties().ToList().ForEach(
     x => datatable.Columns.Add(x.Name)); 
    Builder<T>.CreateListOfSize(rows).Build() 
     .ToList().ForEach(
      x => datatable.LoadDataRow(x.GetType().GetProperties().Select(
       y => y.GetValue(x, null)).ToArray(), true)); 
    return datatable; 
} 

var dataset = new DataSet(); 
dataset.Tables.AddRange(new[]{ 
     GenerateDataTable<Person>(50), 
     GenerateDataTable<Dog>(100)}); 
0

En mi experiencia, ha sido bastante fácil haga que las pruebas de extremo a extremo funcionen con Fluent NHibernate. No hay excusa para no usar una capa tan ligera cuando hace tanto por ti.

Persistence specification testing

+0

El enlace está roto ahora – Fedor

+0

@Fedor Se ha actualizado. ¡Buena atrapada! – GregC

0

no hay ninguna herramienta para hacer lo que quiera, porque de sus requisitos de que los datos se almacenan como tablas de datos, y que necesita los datos originales de la base de datos. La parte manual de las herramientas está conectando qué apunta a qué (es decir, sus datos en almacenamiento a su representación de datos en el código). Ya has hecho esta parte, y no es lo que está automatizado.

0

Salida http://nbuilder.org/

"¿Qué es?

A través de una interfaz fluida, extensible, NBuilder le permite crear rápidamente los datos de prueba, la asignación automática de los valores de las propiedades y campos públicos que son de tipo de construido en los tipos de datos .NET (por ejemplo, ints y cadenas). NBuilder le permite anular las propiedades que le interesan usando expresiones lambda. "

Cuestiones relacionadas