Estoy tratando de configurar un DbSet simulado para fines de prueba. Usé el tutorial aquí, http://www.loganfranken.com/blog/517/mocking-dbset-queries-in-ef6/ y lo modifiqué ligeramente para que llamar a GetEnumerator devuelva un nuevo enumerador cada vez (otro problema que estaba teniendo) . Sin embargo, tengo dificultades para agregar elementos al DbSet.
El resultado es preCount = 3 postCount = 3. Sin embargo, espero que sea precount = 3 postCount = 4. Cualquier ayuda es muy apreciada.
static void Main(string[] args) { Debug.WriteLine("hello debug"); List<string> stringList = new List<string> { "a", "b", "c" }; DbSet<string> myDbSet = GetQueryableMockDbSet(stringList); int preCount = myDbSet.Count(); myDbSet.Add("d"); int postCount = myDbSet.Count(); Debug.WriteLine("preCount = " + preCount + " postCount = " + postCount); } private static DbSet<T> GetQueryableMockDbSet<T>(List<T> sourceList) where T : class { var queryable = sourceList.AsQueryable(); var dbSet = new Mock<DbSet<T>>(); dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider); dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression); dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType); dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator()); return dbSet.Object; }myDbSet no es una implementación real de DbSet sino una simulación, lo que significa que es falso y debe configurarse para todos los métodos que necesite. Add no es una excepción, por lo que debe configurarse para hacer lo que necesita; de lo contrario, no hace nada.
Agregue algo como lo siguiente y cuando myDbSet.Add("d"); se llama, la 'd' se agrega a la lista y se puede devolver más tarde.
dbSet.Setup(d => d.Add(It.IsAny<T>())).Callback<T>((s) => sourceList.Add(s)); private static DbSet<T> GetQueryableMockDbSet<T>(List<T> sourceList) where T : class { var queryable = sourceList.AsQueryable(); var dbSet = new Mock<DbSet<T>>(); dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider); dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression); dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType); dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator()); dbSet.Setup(d => d.Add(It.IsAny<T>())).Callback<T>((s) => sourceList.Add(s)); return dbSet.Object; } hello debug preCount = 3 postCount = 4Para manejar .Find() , podemos usar la reflexión de manera similar, con algunas suposiciones sobre las convenciones al utilizar Find .
(Con suerte, esto no está fuera de lugar, he tenido esta pregunta y respuesta marcada durante años y estaba buscando una implementación de Find ...)
Implemente otro ayudante como tal:
static object find(IEnumerable<object> oEnumerable, object[] keys) { // assumptions: primary key of object is named ID // primary key of object is an int // keys passed to .Find() method is a single value of int type foreach (var o in oEnumerable) { var t = o.GetType(); var prop = t.GetProperty("ID"); if (prop != null) { if (prop.PropertyType == typeof(int)) { if ((int)prop.GetValue(o) == (int)keys[0]) { return o; } } } } return null; }y en el ejemplo de configuración simulado proporcionado por Daniel arriba:
dbSet.Setup(d => d.Find(It.IsAny<object[]>())).Returns((object[] oArray) => find(sourceList, oArray) as T); Debido a que no tenemos forma (o deseo, por lo general) de determinar la clave principal de la forma en que lo haría EF, asumo que "ID" es el nombre del campo clave (que coincide con mis propias convenciones), pero esto podría ser expandido para aceptar un número de variaciones. También asumo que solo se pasa un entero a Find (como es mi convención estándar), pero esto también podría expandirse para un soporte más sólido.