2012-04-25 29 views
12

Estoy usando Code First para asignar clases a una base de datos existente. Necesito una forma de probar las unidades de estas asignaciones, que son una combinación de aplicaciones basadas en convenciones, basadas en atributos y fluidas.¿Cómo puedo probar la unidad First Framework Code First Mappings?

Para probar la unidad, necesito confirmar que las propiedades de las clases se asignan a los nombres correctos de tabla y columna en la base de datos. Esta prueba debe realizarse en relación con el contexto, y debe cubrir todas las opciones de configuración para el código primero.

En un nivel muy alto, estaría buscando para afirmar algo así como (pseudo-código):

Assert.IsTrue(context.TableFor<Widget>().IsNamed("tbl_Widget")); 
Assert.IsTrue(context.ColumnFor<Widget>(w => w.Property).IsNamed("WidgetProperty")); 
+1

Bueno, yo no como EF, si es posible evaluar la posibilidad de utilizar NHibernate, con NHibernate puede probar sus asignaciones realmente fácil – Jupaol

+0

@Jupaol es bueno saber, utilizamos EF y NH y tenemos nuestros problemas con ambos – STW

Respuesta

0

La única manera que puedo pensar para cubrir todas las opciones posibles sería el uso de la Entidad Framework Power Tools para precompilar las vistas de su DbContext, y probablemente utilice una combinación de reflejo en ese tipo generado y RegEx en el código generado para verificar todo lo que se le ocurra. Suena bastante doloroso para mí.

Otra cosa que me viene a la mente es crear una fachada alrededor de DbModelBuilder para interceptar y controlar todo lo que pasa a través de ella, pero no sé si eso manejaría las cosas basadas en la convención. También suena doloroso

Como una alternativa menos completa, pero mucho más fácil, probablemente pueda eliminar una gran parte de esto al cambiar a la asignación de atributos siempre que sea posible. Esto permitirá crear una clase de prueba de base, por ejemplo, ModelTesting <TEntity>, que incluye unos métodos de ensayo que utilizan la reflexión para comprobar que tiene TEntity:

  • Una sola TableAttribute.
  • Cada propiedad tiene un solo atributo ColumnAttribute o un atributo NotMappedAttribute.
  • Al menos una propiedad con un KeyAttribute.
  • Cada tipo de propiedad se asigna a un tipo de base de datos compatible.

Incluso podría llegar a imponer una convención de nomenclatura basada en los nombres de las propiedades y la clase (con una advertencia para los tipos de tabla por jerarquía). También sería posible verificar las asignaciones de claves externas también. Es una clase base de una sola escritura que puedes obtener de una vez para cada uno de tus tipos de modelos y atrapar la mayoría de tus errores (bueno, de todos modos captura la mayoría de los míos).

Cualquier cosa que no pueda ser representada por atributos, como la herencia TPH y tal, se vuelve un poco más difícil. Una prueba de integración que desencadena el DbContext y realiza un FirstOrDefault en el conjunto <TEntity>() probablemente cubra la mayoría de esas bases, suponiendo que su DbContext no genere su base de datos por usted.

+0

Gracias por la entrada Sean! Estoy considerando planteamientos menos exhaustivos, como usar un único método de configuración y echar un vistazo a las herramientas eléctricas de EF, no estaba al tanto de ellas. – STW

0

Si usted escribió un método

public static string ToMappingString(this Widget obj) 

Posteriormente, se podría fácilmente a través de las pruebas de este ensayos de homologación (www.approvaltests.com o Nuget)

Hay un video aquí: http://www.youtube.com/watch?v=vKLUycNLhgc

Sin embargo, si usted está buscando para probar "Mis objetos guardar y retrive a sí mismos" entonces este es un lugar perfecto de la "Teoría de las pruebas basadas en"

Teoría pruebas basadas la mayoría de pruebas unitarias toman la forma de

Given A,B expect C 

Teoría pruebas basadas es

Given A,B expect Theory 

La belleza de esto es que no hay necesidad de preocuparse de qué forma particular Una toma & B, ya que no es necesario saber C, por lo que cualquier generador aleatorio funcionará.

Ejemplo 1: Prueba de sumar y restar métodos

Normalmente usted tendría cosas como

Assert.AreEqual(5, Add(2,3)); 
Assert.AreEqual(9, Add(10,-1)); 
Assert.AreEqual(10, Add(5,5)); 
Assert.AreEqual(7, Subtract(10,3)); 

Sin embargo, si usted escribió una prueba de la teoría que se vería así

for(int i = 1; i < 100; i++) 
{ 
    int a = random.Next(); 
    int b = random.Next(); 
    Assert.AreEqual(a, Subtract(Add(a,b),b, string.Format("Failed for [a,b] = [{0},{1}], a,b));   
} 

Ahora que ya Comprenda las pruebas basadas en la teoría, la teoría que intenta probar es

Given Model A 
When A is stored to the database, and retrieved the resulting object is equal to A 
1

Otra idea a considerar es usar Linq y ToString().

Para eaxample esto:

context.Widget.Select(c => c.Property).ToString() 

resultará en esto para SQL Server proveedor:

"SELECT [Var_3].[WidgetProperty] AS [WidgetProperty] FROM [dbo].[Widget]..." 

ahora podríamos ocultarlo todo en algún método de extensión que y analiza resultante de SQL que se vería casi Al igual que su pseudo-código:

Assert.IsTrue(context.Widgets.GetSqlColumnNameFor(w => w.Property).IsNamed("WidgetProperty")); 

Proyecto de la extensión:

public string GetSqlColumnNameFor<TSource>(this DbSet<T> source, Expression<Func<TSource, TResult>> selector) 
{ 
    var sql = source.Select(selector).ToString(); 

    var columnName = sql... // TODO : Some regex parsing 

    return 
     columnName; 
} 

Similarmente podríamos crear GetSqlTableNameFor().

ACTUALIZACIÓN: decidí buscar algunos analizadores dedica SQL, por lo que esta solución es más genérico, obviamente, hay una cosa para .NET:

http://www.dpriver.com/blog/list-of-demos-illustrate-how-to-use-general-sql-parser/generate-internal-query-parse-tree-in-xml-for-further-processing/

Cuestiones relacionadas