2009-04-07 10 views
14

Estoy dando mis primeros pasos con MsTest y Moq y me gustaría probar una unidad de una clase de repositorio Linq2SQL. El problema es que no quiero que las pruebas de la unidad modifiquen permanentemente mi base de datos de desarrollo.Unidad probando un repositorio LINQ2SQL

¿Cuál sería el mejor enfoque para este escenario?

  • Que cada prueba de operar en mi base de datos de desarrollo de bienes, pero asegúrese de que cada prueba se limpia después de sí mismo
  • crear un duplicado de mi base de datos de desarrollo y dbml para la prueba de la unidad y utilizar ese contexto lugar para que pueda borrar toda la base de datos antes de cada ejecución de prueba
  • Encuentra alguna forma elaborada de burlarse del Datacontext (ten en cuenta que soy un novato total de Moq).
  • ¿Algo completamente diferente? ¿Tal vez algo que automatizaría la configuración de la base de datos antes de cada prueba?

Editar: acabo aprendido que MbUnit tiene un atributo de reversión que invierte cualquier operación de base de datos a cargo de un caso de prueba. No estoy particularmente apegado a MSTest, ¿podría ser una respuesta fácil a mi problema?

Respuesta

1

jugué un poco con MbUnit y supe que, para la mayoría de los casos de prueba, que puede salirse sin burlarse del DataContext mediante el uso de atributos [ROLLBACK] de MbUnit .

Desafortunadamente, también hay casos en los que el atributo produce efectos secundarios extraños, como cargar una entidad linq de la base de datos, cambiar una propiedad (sin enviar cambios) y luego cargar la misma entidad nuevamente. Por lo general, esto no genera ninguna consulta de actualización en la base de datos, pero desde el Método de prueba, parece que la actualización se ejecuta inmediatamente tan pronto como cambio la propiedad de la entidad linq.

No es una solución perfecta, pero creo que voy a ir con el atributo [ROLLBACK] ya que es menos esfuerzo y funciona bastante bien para mí.

14

Fui con burlona/falsificar la base de datos usando algunas clases contenedoras + una implementación basada en falso http://andrewtokeley.net/archive/2008/07/06/mocking-linq-to-sql-datacontext.aspx. Tenga en cuenta que terminé implementando la lógica SubmitChanges en mi contenedor de contexto de datos falso para probar la lógica de validación en la implementación de la clase parcial de mi entidad. Creo que esta fue realmente la única parte difícil que difirió sustancialmente de la implementación de Tokeley.

Voy a incluir mi implementación FakeDataContextWrapper a continuación:

public class FakeDataContextWrapper : IDataContextWrapper 
{ 

    public DataContext Context 
    { 
     get { return null; } 
    } 

    private List<object> Added = new List<object>(); 
    private List<object> Deleted = new List<object>(); 

    private readonly IFakeDatabase mockDatabase; 

    public FakeDataContextWrapper(IFakeDatabase database) 
    { 
     mockDatabase = database; 
    } 

    protected List<T> InternalTable<T>() where T : class 
    { 
     return (List<T>)mockDatabase.Tables[typeof(T)]; 
    } 

    #region IDataContextWrapper Members 

    public virtual IQueryable<T> Table<T>() where T : class 
    { 
     return mockDatabase.GetTable<T>(); 
    } 

    public virtual ITable Table(Type type) 
    { 
     return new FakeTable(mockDatabase.Tables[type], type); 
    } 

    public virtual void DeleteAllOnSubmit<T>(IEnumerable<T> entities) where T : class 
    { 
     foreach (var entity in entities) 
     { 
      DeleteOnSubmit(entity); 
     } 
    } 

    public virtual void DeleteOnSubmit<T>(T entity) where T : class 
    { 
     this.Deleted.Add(entity); 
    } 

    public virtual void InsertAllOnSubmit<T>(IEnumerable<T> entities) where T : class 
    { 
     foreach (var entity in entities) 
     { 
      InsertOnSubmit(entity); 
     } 
    } 

    public virtual void InsertOnSubmit<T>(T entity) where T : class 
    { 
     this.Added.Add(entity); 
    } 

    public virtual void SubmitChanges() 
    { 
     this.SubmitChanges(ConflictMode.FailOnFirstConflict); 
    } 

    public virtual void SubmitChanges(ConflictMode failureMode) 
    { 
     try 
     { 
      foreach (object obj in this.Added) 
      { 
       MethodInfo validator = obj.GetType().GetMethod("OnValidate", BindingFlags.Instance | BindingFlags.NonPublic); 
       if (validator != null) 
       { 

        validator.Invoke(obj, new object[] { ChangeAction.Insert }); 
       } 
       this.mockDatabase.Tables[obj.GetType()].Add(obj); 
      } 

      this.Added.Clear(); 

      foreach (object obj in this.Deleted) 
      { 
       MethodInfo validator = obj.GetType().GetMethod("OnValidate", BindingFlags.Instance | BindingFlags.NonPublic); 
       if (validator != null) 
       { 
        validator.Invoke(obj, new object[] { ChangeAction.Delete }); 
       } 
       this.mockDatabase.Tables[obj.GetType()].Remove(obj); 
      } 

      this.Deleted.Clear(); 

      foreach (KeyValuePair<Type, IList> tablePair in this.mockDatabase.Tables) 
      { 
       MethodInfo validator = tablePair.Key.GetMethod("OnValidate", BindingFlags.Instance | BindingFlags.NonPublic); 
       if (validator != null) 
       { 
        foreach (object obj in tablePair.Value) 
        { 
         validator.Invoke(obj, new object[] { ChangeAction.Update }); 
        } 
       } 
      } 
     } 
     catch (TargetInvocationException e) 
     { 
      throw e.InnerException; 
     } 
    } 

    public void Dispose() { } 

    #endregion 
} 
+1

Sí, es lo que hice también. Eso y creó pruebas de integración que se ejecutaban en una base de datos. Linq to Sql es bastante bueno en ese aspecto: puedes nukear y crear la base de datos directamente desde el contexto de datos. – Will

2

Tuve una necesidad similar: probar las clases de Linq a Sql, así que hice un pequeño conjunto de clases para obtener el contexto de datos simulado, ITables y IQueryables en las consultas.

Puse el código en una publicación de blog "Mock and Stub for Linq to Sql". Utiliza Moq, y puede proporcionar suficiente funcionalidad para las pruebas que estás buscando sin golpear la base de datos.

Cuestiones relacionadas