2014-09-10 29 views
8

üzerinde test başarısız Birim testi bunu test etmek mümkün mü? EF Entry.State

public class MyRepository<T> where T : IdentityUser, new() 
{ 
    public async Task UpdateAsync(T user) 
    { 
     _context.Entry(user).State = EntityState.Modified; 
     _context.Entry(user).Property("UserName").IsModified = false; 
     await _context.SaveChangesAsync(); 
    } 
} 

[TestInitialize] deposunda

_user = new IdentityUser { Id = "70a038cdde40" }; 

IDbSet<IdentityUser> users = new FakeDbSet<IdentityUser> { _user }; 

var dbContext = new Mock<MyDbContext<IdentityUser>>(); 
dbContext.Setup(x => x.Users).Returns(() => users); 

_repository = new MyRepository<IdentityUser>(dbContext.Object); 

1 kullanıcıyı ekler ve bu

private MyRepository<IdentityUser> _repository; 

[TestMethod] 
public async Task UpdateUser_Success2() 
{ 
    var user = await _repository.FindByIdAsync("70a038cdde40"); 
    Assert.IsFalse(user.EmailConfirmed, "User.EmailConfirmed is True"); 

    user.EmailConfirmed = true; 

    await _repository.UpdateAsync(user); 

    (...) 
} 

ile test etmek çalışıyorum Ama UpdateAsync 1. satırda ölür. Test yanlış mı yoksa UpdateAsync uygulaması mı? Test edebileceğim herhangi bir yolu var mı? olmayan bir sanal üyesinde geçersiz kurulum: Belogix sanırım, ama yine de sanal olmayan hata var, daha yakın beni alır

dbContext.Setup(x => x.Entry(It.IsAny<IdentityUser>())) 
         .Returns(() => dbContext.Object.Entry(_user)); 

önerdiği gibi

Düzenleme

ekledim: x => x.Entry (It.IsAny())

+0

Eğer testi? Bir şey ya da gerçek bir şey alay (bir DB işaret)? İlgili parçaları gömdünüz mü? – Belogix

+0

@Belogix Sorularıma cevap verdiğimi umuyoruz – kooshka

+0

Hayır, yakınım ama cevabınıza bakarsanız 'Entry' ile 'user' değil 'State' i dönmek için alay etmeniz gerekir. Öyleyse, 'Entry' alayımı örneğimi kullan ve tekrar dene ... Bu şekilde, sahte nesne üzerinde devleti vs. ayarlayabilirsin. Umarım bu mantıklıdır! – Belogix

cevap

5

Şimdiye kadarki en iyi alıntı: "Bilgisayar bilimlerindeki tüm problemler, bir başka indirgeme seviyesiyle çözülebilir" - Butler Lampson.

Bazı ek soyutlamalar eklemeden doğrudan test edilemez gibi görünüyor. Ben bu yolu benim UpdateAsync yöntemi

public async Task UpdateAsync(T user) 
{ 
    SetEntityStateModified(user); 
    SetPropertyIsModified(user); 
    await _context.SaveChangesAsync(); 
} 

public virtual void SetPropertyIsModified(T user) 
{ 
    _context.Entry(user).Property("UserName").IsModified = false; 
} 

public virtual void SetEntityStateModified(T user) 
{ 
    _context.Entry(user).State = EntityState.Modified; 
} 

planı ayrı Sonra sonra nihayet DBContext içinde ChangeTracker değişiklikleri izler

[TestMethod] 
public async Task can_update_user_details() 
{ 
    //Arrange 
    var user = await _repository.Object.FindByIdAsync("70a038cdde40"); 
    Assert.IsFalse(user.EmailConfirmed, "User.EmailConfirmed is True"); 

    //Act    
    user.EmailConfirmed = true; 

    await _repository.Object.UpdateAsync(user); 
    var newUser = await _repository.Object.FindByIdAsync("70a038cdde40"); 

    //Assert 
    Assert.IsTrue(newUser.EmailConfirmed, "User.EmailConfirmed is False"); 
} 
-1

context numaralı dosyanızın doğru yönlendirilmediğini görüyoruz ... Visual Studio yüklü bir bilgisayarda değilim, bu yüzden burada ne olduğunu gösteren bazı sözde kodlar var. anlamına gelmek. IsAnything'u ya alay çerçevelerinizi, bağımsız yanıtları görmezden gelme şeklinizle veya farklı yanıtları işlemek istiyorsanız gerçekten de kullanıcıyla değiştirin.

// Existing context initialisation... 
var dbContext = new Mock<MyDbContext<IdentityUser>>(); 
dbContext.Setup(x => x.Users).Returns(() => users); 

// NEW: Mock what/how Entry is going to return when called (i.e. return a user) 
dbContext.Setup(x => x.Entry(IsAnything)).Returns(() => users[0]); 
+3

EntityFramework'da giriş sanal olmadığından bu işe yaramaz, bu nedenle kullanılamaz – tocqueville

0

geçer başlat içinde

_repository = new Mock<MyRepository<IdentityUser>>(dbContext.Object); 
_repository.Setup(x => x.SetEntityStateModified(It.IsAny<IdentityUser>())); 
_repository.Setup(x => x.SetPropertyIsModified(It.IsAny<IdentityUser>())); 

Benim testi benim test kodunu güncellemek zorunda ve değiştirilen varlıkları tutun. Böylece değişen varlığın onların arasında olduğunu iddia edebilirsiniz. Böyle bir şey olurdu özellik için

Assert.IsTrue(dbContext.Object.ChangeTracker.Entries().Any(entry => 
      entry.State == EntityState.Modified && 
      entry.Entity is IdentityUser && 
      (entry.Entity as IdentityUser).Id == users[0].Id // Here you can check if it is actually the same user 
     )); 

:

noktada `_context` nedir
Assert.IsTrue(_context.Object.ChangeTracker.Entries().Any(entry => 
      entry.Property("UserName").IsModified == false && 
      entry.Entity is IdentityUser && 
      (entry.Entity as IdentityUser).Id == users[0].Id // Here you can check if it is actually the same user 
     ));