2012-11-14 94 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(); 
} 

而且我想單元測試,如果驗證潔具正確。我使用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"); 
} 

我的測試失敗。
雖然我正在調試,我可以看到引發異常,提交沒有被調用。但是我的用戶在Address屬性中仍然存在「一些新的虛假用戶地址」,儘管我期待它會被回滾。
雖然我在nhibernate分析器中查看,但我可以看到開始事務語句,但它既沒有被提交也沒有被回滾。
更重要的是,即使我在那裏放置了try-catch塊並在捕獲中明確回滾,我的測試仍然失敗。
我認爲,測試環境中存在一些問題,但對我來說一切似乎都很好。

任何想法?

編輯:我已經添加了重要的try-catch塊(開始時我已經簡化了代碼太多)。

回答

3

如果在NH刷新對數據庫的更改之前發生異常,並且如果您繼續使用該會話而不清除/清除對象,並且出於某種原因稍後發生刷新,則該更改仍將保留,因爲根據NHibernate,對象仍然很髒。回滾事務時,應立即關閉會話以避免此類問題。

另一種說法是:回滾不會回滾您對持久實體所做的內存更改。

此外,如果會話是常規會話,則不需要調用Save(),因爲實例已由NH進行跟蹤。

+0

感謝您的回答。你寫的是真的,但是在真正的代碼中有Foo()中的try-catch塊,我忘了在開頭寫。抱歉,是我的錯!所以我仍然不知道問題出在哪裏。 – Przecinek

+0

@Przecinek我看了你的更新代碼。 Foo()中的try-catch具有吞噬異常的效果,這意味着When()將繼續,就好像什麼也沒有發生。由於對Foo()的調用之後是對session.Flush()的調用,因此在調用Clear()之前,您在Foo()中所做的更改現在將被推送到數據庫。這是我上面描述的答案。 –