2012-11-14 2 views
2

나는 다음과 같다 코드 조각이있어 :NHibernate에 거래 및 단위 테스트

public void Foo(int userId) 
{ 
    try { 
     using (var tran = NHibernateSession.Current.BeginTransaction()) 
     { 
      var user = _userRepository.Get(userId); 
      user.Address = "some new fake user address"; 
      _userRepository.Save(user); 
      Validate(); 
      tran.Commit(); 
     } 
    } 
    catch (Exception) { 
     logger.Error("log error and don't throw") 
    } 
} 

private void Validate() 
{ 
    throw new Exception(); 
} 

을 그리고 검증이 제대로 이루어 도자기 경우 I는 단위 테스트를하고 싶습니다. 나는 테스트를 위해 nunit과 SQLLite 데이터베이스를 사용한다. 다음은 테스트 코드입니다.

protected override void When() 
{ 
    base.When(); 
    ownerOfFooMethod.Foo(1); 
    Session.Flush(); 
    Session.Clear(); 
} 

[Test] 
public void FooTest() 
{ 
    var fakeUser = userRepository.GetUserById(1); 
    fakeUser.Address.ShouldNotEqual("some new fake user address"); 
} 

내 테스트가 실패합니다.
디버깅하는 동안 예외가 throw 된 것을 볼 수 있지만 Commit은 호출되지 않았습니다. 하지만 내 사용자가 여전히 롤백 될 것으로 예상했지만 Address 속성에 "새로운 가짜 사용자 주소"가 있습니다.
내가 nhibernate 프로파일 러를보고있는 동안 트랜잭션 문을 시작할 수 있지만 커밋이나 롤백 중 어느 것도 따르지 않습니다.
심지어 try-catch 블록을 넣고 catch에서 롤백을 명시 적으로 수행하더라도 테스트가 여전히 실패합니다.
테스트 환경에는 약간의 문제가 있지만 모든 것이 잘 될 것 같습니다.

아이디어가 있으십니까?

편집 : 중요한 try-catch 블록을 추가했습니다. 처음에는 코드를 너무 단순화했습니다.

답변

3

NH이 데이터베이스에 변경 사항을 플러시하기 전에 예외가 발생하고 개체를 제거/지우지 않고 해당 세션을 계속 사용하면 나중에 어떤 이유로 플러시가 발생해도 변경 내용은 계속 유지됩니다. 객체는 NHibernate에 따라 여전히 더럽다. 트랜잭션을 롤백 할 때 이러한 종류의 문제를 피하려면 세션을 즉시 닫아야합니다.

또 다른 방법 : 롤백은 영구 엔터티에 대한 메모리 내 변경 사항을 롤백하지 않습니다.

또한 세션이 일반 세션 인 경우 인스턴스가 NH에 의해 이미 추적되므로 Save()에 대한 호출이 필요하지 않습니다.

+0

답변 해 주셔서 감사합니다. 당신이 작성한 것은 사실 일 것이지만, 실제 코드에는 Foo()에서 try-catch 블록이 있습니다. 처음에 작성하는 것을 잊어 버렸습니다. 미안, 내 실수! 그래서 나는 아직도 문제가 어디 있는지 전혀 모른다. – Przecinek

+0

@Przecinek 업데이트 된 코드를 살펴 보았습니다. Foo()의 try-catch는 예외를 삼키는 효과가 있습니다. 즉, 아무 일도 일어나지 않은 것처럼 When()가 계속됩니다. Foo()를 호출 한 후 session.Flush()를 호출하면 Foo()에서 변경 한 내용이 Clear() 호출 전에 데이터베이스로 푸시됩니다. 이것은 위의 대답이 설명하는 상황입니다. –