2014-09-10 2 views
8

단위 테스트가 가능합니까? 단위 테스트가 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]은 저장소

_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 사용자를 추가하고 나는이

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

    (...) 
} 

으로 테스트하기 위해 노력하고있어하지만 UpdateAsync의 첫번째 줄에 죽는다. 테스트가 잘못되었거나 UpdateAsync 구현입니까? 내가 그것을 테스트 할 수있는 방법이 있습니까? 가상이 아닌 구성원의 잘못된 설정 : Belogix 나는 생각하지만, 여전히 비가 상 오류가 가까이 저를 얻을 수

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

에 의해 제안

편집

내가 추가 : x => x.Entry (It.IsAny())

+0

당신은 당신의 테스트를 실행? DB를 가리키는 무언가 또는 실물의 조롱? 관련 부품을 스터브 했으므로 전화가 모두 연결됩니다. – Belogix

+0

@Belogix 나는 당신의 대답에 대한 희망을 업데이트했습니다. – kooshka

+0

아니요, 닫습니다.하지만 내 대답을 보면'entry'가'user'가 아니라'State'가 아닌 클래스를 반환 할 수있는 모의이 필요합니다 ... 그래서'Entry'를 조롱하는 예제를 사용하고 다시 시도하십시오 ... 그런 식으로 그 모의 객체에 상태 등을 설정할 수 있습니다. 희망은 그것이 의미가 있습니다! – Belogix

답변

5

"컴퓨터 과학의 모든 문제는 다른 수준의 간접적 인 방법으로 해결할 수 있습니다"- Butler Lampson.

추가 추상화를 추가하지 않으면 직접 테스트 할 수없는 것처럼 보입니다. 나는 이런 식으로 내 UpdateAsync 방법

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

를 리팩토링 그리고 다음 마지막으로 dbContext의 ChangeTracker 변경 사항을 추적

[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을 스텁하지 않은 것처럼 보입니다. Visual Studio를 사용하는 컴퓨터가 아닙니다. 그래서 여기에 몇 가지 의사 코드가 있습니다. 평균. IsAnything을 논평을 무시하는 조롱 프레임 워크 방식 또는 다른 응답을 처리하려는 경우 실제로 사용자로 대체하십시오.

+3

Entry가 EntityFramework에서 가상이 아니므로 모의 객체가 아니기 때문에이 기능이 작동하지 않습니다. – tocqueville

0

를 전달 초기화에

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

내 테스트를 내 테스트 코드를 업데이트했다 변경된 엔티티를 보유합니다. 따라서 변경된 엔티티가 그 중 하나라고 주장 할 수 있습니다. 그것은이 같은 것 속성에 대한

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

는 :

지점에서`_context`은 무엇입니까
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 
     )); 
관련 문제