2015-07-10 27 views
20

Deneme amacıyla sahte bir DbSet kurmaya çalışıyorum. Burada, http://www.loganfranken.com/blog/517/mocking-dbset-queries-in-ef6/ eğitimini kullandım ve biraz değiştirdim, böylece GetEnumerator her seferinde yeni bir numaralayıcı döndürüyor (başka bir sorunla karşılaşıyordum). Ancak, DbSet'e öğe eklerken güçlük çekiyorum.Mock DbSet'e öğe ekleme (Moq kullanarak)

Çıktı preCount = 3 postCount = 3'tür. Ancak, precount = 3 postCount = 4 olmasını beklerim. Herhangi bir yardım büyük beğeni topluyor.

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; 
    } 
+0

Çok güzel yöntem. Senkronize olmayan sorguları desteklemek için bunu herhangi bir şekilde güncellediniz mi? –

+0

Bu, en azından şu an için .net core 1.0 ile, async sorununu yanıtlayacaktır: [Bir Varlık Deposu ile birlikte bir async deposu nasıl kopyalanır] (https://stackoverflow.com/questions/40476233/how-to-mock -en-async-varlık-çerçeve-çerçeve-çekirdek) –

cevap

53

myDbSet gerçek DbSet uygulanması ancak sahte ve o size gerekli olan tüm yöntemleri için kurulum olması gerektiği anlamına gelir sahte değildir. Add istisna değildir, bu yüzden ihtiyacınız olanı yapmak için ayarlanması gerekir, aksi takdirde hiçbir şey yapmaz.

Aşağıdaki gibi bir şey ekleyin ve myDbSet.Add("d"); çağrıldığında, 'd' listeye eklenir ve daha sonra geri gönderilebilir.

dbSet.Setup(d => d.Add(It.IsAny<T>())).Callback<T>((s) => sourceList.Add(s)); 

Komple kod

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; 
} 

Çıktı dbSet oluşturarak saklanması

hello debug 
preCount = 3 postCount = 4 
+0

Sorun şu ki, veritabanına bir şey eklediğinizde, gezinme özelliklerini elle ayarlamanız gerekir, bu alay ise nesneyi olduğu gibi kaydedecektir. EF'in bu konuda davranışını taklit etmenin bir yolu var. – tocqueville

+2

EF alay konusu, testlerinize bir veritabanı getirmeniz istenmediği içindir. Sadece belirli bir API'yi test eden hızlı çalışan, bölümlere ayrılmış testlere sahip olmak daha iyidir. Başka bir seçenek https://msdn.microsoft.com/en-us/data/dn314431.aspx "bellek içi çift", ancak bellek içi ikiye katlama ve alay aslında aynı şeydir. – andrew

+0

Senkronize olmayan sorguları desteklemek için bunu herhangi bir şekilde güncellediniz mi? –