unit-testing mocking data-access-layer

unit testing - Burla vs. Prueba DB?



unit-testing mocking (8)

Al utilizar una base de datos de prueba, se abre la posibilidad de que se puedan causar problemas en la base de datos o en la ruta de comunicación (red, etc.) entre el DAL y la base de datos. Burlarse elimina esas posibilidades.

Anteriormente, hice esta pregunta ¿Cómo puedo probar mi DAL correctamente? , una cosa que queda sin respuesta para mí es si realmente probar mi DAL es tener una prueba DB, entonces ¿cuál es el papel de la burla vs. una prueba DB?

Para agregar esto, otra persona sugirió "usar transacciones y retrotraer al final de la prueba unitaria, para que el db esté limpio", es decir, prueba db. ¿Qué piensan ustedes de este método de prueba + prueba DB + reversión de transacción (entonces, db realmente no está escrito) para probar DAL?

Para estar completo, mi DAL está construido con Entity Framework, no hay ningún proceso almacenado en DB. Dado que EF es tan nuevo, realmente necesito probar DAL para asegurarme de que funcionan correctamente.


Creo que probablemente quiera hacer algunas pruebas de integración para verificar la lógica que impone la estructura de su base de datos, por ejemplo, restricciones, desencadenantes, columnas de autoincrement, etc. Sin embargo, para las pruebas de unidades, debe simular los componentes de estructura que su DAL se basa en lo que desee (en las pruebas de su unidad) para probar solo los componentes que ha codificado. Realmente no necesita probar métodos en SqlCommand o SqlConnection (por ejemplo). Debe suponer que los componentes de framework que utiliza funcionan y crean stubs o burlas para ellos que devuelven datos conocidos (buenos, malos, excepciones) a sus métodos para asegurarse de que sus métodos funcionen correctamente. Sin burlarse, usted es responsable de generar los datos en la base de datos y asegurarse de que sean correctos. También deja dependencias abiertas en la red, la base de datos en sí, etc. que pueden hacer que sus pruebas sean frágiles.

Además, las pruebas unitarias no eliminan la necesidad de otros tipos de pruebas. Las pruebas de integración y las pruebas de aceptación siguen siendo válidas y deben realizarse. Probablemente no necesiten hacerlo con la misma frecuencia que las pruebas unitarias y puede que no necesite ser tan extenso como mejora la calidad del código con las pruebas unitarias, pero las pruebas unitarias no son una solución mágica.


No encontré el burlarse muy útil cuando probaba el código de acceso a datos. El propósito de las pruebas unitarias es verificar que el código relacionado con la base de datos funcione y burlarse de la base de datos podría dificultar la prueba.

La burla sí se vuelve útil cuando se prueba el código comercial. Puede simular sus llamadas a la base de datos para devolver datos de prueba y verificar el comportamiento de la lógica comercial en esas circunstancias.

En cuanto al uso de transacciones, es ciertamente posible, siempre y cuando su arquitectura tenga espacio para iniciar una transacción al comienzo de la prueba, y luego hacer todas las llamadas relacionadas con la base de datos de su unidad de prueba dentro de esa transacción. Nunca lo intenté, sin embargo.


hemos utilizado pruebas de unidades transaccionales y eso impidió varias veces los problemas de mapeo de Hibernate. De lo contrario, ¿qué hay para probar la unidad? Algo trivial como List<Item> getAllItems() ? :)


No es solo el estado de la base de datos que debe considerar, también es la disponibilidad. Si su DB está fuera de línea, ¿por qué deberían fallar todas sus pruebas DAL?

Lo que necesita probar es que su DAL emite los comandos correctos para crear / recuperar / actualizar / eliminar. No necesita ejecutar SQL para esto, solo puede usar un marco de persistencia de objetos y verificar que le dé las instrucciones correctas.


Poner pruebas unitarias en transacciones que retroceden suena a hacky. En lugar de eso, tengo un código que limpia la base de datos de cualquier crud (es decir, cualquier cosa que no sea estática / datos de referencia) antes de que se ejecuten las pruebas (es decir, en el constructor de mi clase de prueba). Cuando sus pruebas fallan, es útil tener los datos aún en la base de datos para inspeccionar cuál es la causa de la falla.


No solo estás probando tu aplicación. También está probando su configuración y sus procedimientos almacenados y vistas. Estos están documentados en las pruebas de su unidad.


El problema podría estar en la pregunta original. Algunos de los ejemplos más populares de MVC usan un acceso directo devolviendo un DbSet como:

public class MusicStoreEntities : DbContext { public DbSet<Album> Albums { get; set; } public DbSet<Genre> Genres { get; set; } public DbSet<Artist> Artists { get; set; } public DbSet<Cart> Carts { get; set; } public DbSet<Order> Orders { get; set; } public DbSet<OrderDetail> OrderDetails { get; set; } }

Para mí, esto estrecha la implementación de la persistencia que creo que es algo malo. Sería mejor devolver List<t> que podría ser fácilmente burlado.