2009-02-22 22 views
34

estoy unidad de código de prueba escrita contra el .NET Framework Entidad ADO. Me gustaría rellenar una base de datos en memoria con filas y asegurarme de que mi código las recupere correctamente.¿Hay un proveedor en memoria para Entity Framework?

que pueden burlarse de los Entity Framework utilizando burla de Rhino, pero eso no sería suficiente. Diría la consulta qué entidades me devolverán. Esto tampoco probaría la cláusula where ni las sentencias .Include(). Quiero estar seguro de que mi cláusula where coincide solo con las filas que intento, y no con otras. Quiero estar seguro de haber pedido las entidades que necesito, y ninguna que no tenga.

Por ejemplo:

class CustomerService 
{ 
    ObjectQuery<Customer> _customerSource; 
    public CustomerService(ObjectQuery<Customer> customerSource) 
    { 
     _customerSource = customerSource; 
    } 
    public Customer GetCustomerById(int customerId) 
    { 
     var customers = from c in _customerSource.Include("Order") 
      where c.CustomerID == customerId 
      select c; 
     return customers.FirstOrDefault(); 
    } 
} 

Si me burlo del ObjectQuery para volver a un cliente conocido poblado de órdenes, ¿cómo sé que a Cliente tiene el derecho cláusula where e Incluir? Preferiría insertar algunas filas de clientes y algunas filas de pedidos, y luego afirmar que se seleccionó al cliente correcto y que los pedidos se completaron.

+1

Al igual que terminaste haciendo, he utilizado interfaces para seguir el Patrón de repositorio y el patrón de Unidad de trabajo. Entonces, tengo dos espacios de nombres -> EF y Fake. Con mi repositorio falso, acabo de utilizar IList para almacenar mis cosas y aprovechar Linq a los objetos para extraer los datos. Funciona muy bien :) –

+4

EntityFramework 7 tiene el proveedor InMemoery ahora. Aún beta como comentario pero si te suscribes al nuget nocturno puedes obtenerlo. – ppumkin

Respuesta

7

Actualmente no existe un proveedor de memoria para EF, pero si echa un vistazo a Highway.Data tiene una interfaz de abstracción básica y un InMemoryDataContext.

Testing Data Access and EF with Highway.Data

+8

Esta ya no es la respuesta correcta. EF7 ahora es compatible con InMemory ... bueno, cuando se lanza en un futuro no muy lejano. – ppumkin

+3

Está en Beta a partir de este escrito. Busque EntityFramework.InMemory en NuGet. – HiredMind

+0

Mientras que EF7 incluirá un proveedor de InMemory ... Entiendo que el proveedor de InMemory está muy abstraído ya que imita las características comunes de todos los proveedores. Tendrá que utilizar algo como el proveedor EntityFramework.SqlLite para pruebas unitarias que requieren la validación de ciertos conceptos específicos del proveedor. Por ejemplo, no pude verificar restricciones únicas ni restricciones de campo requeridas usando el proveedor de InMemory. Tampoco puede validar restricciones relacionales con él. Más detalles aquí: https://github.com/aspnet/EntityFramework/issues/2166 – Paul

2

No estoy familiarizado con el marco de la entidad y la clase ObjectQuery pero si el método es virtual Incluir puedo burlarme de esta manera:

// Arrange 
var customerSourceStub = MockRepository.GenerateStub<ObjectQuery<Customer>>(); 
var customers = new Customer[] 
{ 
    // Populate your customers as if they were coming from DB 
}; 
customerSourceStub 
    .Stub(x => x.Include("Order")) 
    .Return(customers); 
var sut = new CustomerService(customerSourceStub); 

// Act 
var actual = sut.GetCustomerById(5); 

// Assert 
Assert.IsNotNull(actual); 
Assert.AreEqual(5, actual.Id); 
+0

Hay dos características del método GetCustomerById: la cláusula where y el include. Si me burlo de la fuente del cliente para devolver un cliente conocido, no estoy probando ninguno de ellos. –

+0

Si se burla del método Include, no está devolviendo un cliente conocido sino una lista de clientes conocidos para que pueda probar la cláusula where para ver si encuentra al cliente mediante su id. En cuanto al método Include, también verifica que lo llame con el argumento correcto: Orden –

6

Sí, hay al menos un proveedor de tales - SQLite. Lo he usado un poco y funciona. También puedes probar SQL Server Compact. Es una base de datos incrustada y también tiene proveedores de EF.
Editar:
SQLite tiene soporte para bases de datos en memoria (link1). Todo lo que necesita es especificar una cadena de conexión como: "Data Source =: memory:; Version = 3; New = True;". Si necesita un ejemplo, puede mirar SharpArchitecture.

+0

Podría usar una base de datos incrustada (en proceso), pero preferiría ir completamente en memoria. Me gustaría definir mis tablas y llenar algunas filas completamente en código, y nunca escribir nada en el disco. Entonces podría hacer que la prueba de la unidad verifique que mi CustomerService consulte esos datos correctamente. –

+0

SQLite admite bases de datos en memoria, consulte la respuesta editada. – zihotki

+0

Preferiría una ejecución de base de datos real dentro de la memoria porque lo más importante para probar es relaciones y restricciones de base de datos y tiene poco soporte para eso en el código. Lo que me molesta es que esta es la lógica de la aplicación y debería estar representada en su modelo y no en la base de datos. – terjetyl

10

Un mejor enfoque aquí podría ser la de utilizar el patrón de repositorio para encapsular el código de EF. Al probar sus servicios, puede usar simulaciones o falsificaciones. Al probar sus repositorios, querrá acceder a la base de datos real para asegurarse de obtener los resultados que espera.

+0

Si me burlo del depósito para devolver un determinado cliente, esto no prueba la especificación. Quiero incluir la especificación en la prueba de unidad y no esperar hasta que esté usando una base de datos real. –

+1

Lol .. ¿Y cómo se pueden probar las consultas de LINQ2Entities con el patrón Repositorio? No hay forma de hacerlo porque estas consultas generarán consultas SQL y también debemos probarlas en la base de datos. – zihotki

+1

Estoy aceptando esta respuesta porque es lo más parecido a lo que realmente hice. Creé interfaces en la forma del patrón Repository, luego implementé un adaptador EF y un arnés de prueba en memoria. No prueba la base de datos, pero sí prueba mis propias especificaciones. –

1

Usted podría intentar SQL Server Compact pero tiene algunas limitaciones bastante salvajes:

  • SQL Server Compact no admite expresiones SKIP en las consultas de paginación cuando se utiliza con Entity Framework
  • SQL Server Compact no admite entidades con claves o valores generados por el servidor cuando se utiliza con el Entity Framework
  • Sin combinaciones externas, cotejar, módulo en los flotadores, los agregados
16

Un proveedor de InMemory está incluido en EF7 (pre-release).

Puede usar el NuGet package, o leer sobre él en el EF repo en GitHub (view source).

+4

Si bien es cierto, EF7 todavía está en fase de lanzamiento y Microsoft ha declarado que EF7 NO es simplemente el siguiente versión de EF6; por eso lo han renombrado EF Core 1.0 –

+0

Nuestro equipo decidió no tocar EF7 hasta que se implementen tipos complejos y TPT. EF7 es demasiado crudo. – Shimmy

0

En EF Core hay dos opciones principales para hacer esto:

  1. SQLite in-memory mode le permite escribir pruebas eficaces contra un proveedor que se comporta como una base de datos relacional.
  2. The InMemory provider es un proveedor ligero que tiene dependencias mínimas, pero no siempre se comporta como una base de datos relacional

estoy usando SQLite y es compatible con todas las consultas, que tengo que ver con la producción de base de datos SQL Azure.