休眠事务和单元测试

Posted

技术标签:

【中文标题】休眠事务和单元测试【英文标题】:nhibernate transactions and unit testing 【发布时间】:2012-11-14 15:11:05 【问题描述】:

我有一段看起来像这样的代码:

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

我的测试失败了。 在调试时,我可以看到抛出了异常,但尚未调用 Commit。但是我的用户在 Address 属性中仍然有“一些新的假用户地址”,尽管我预计它会被回滚。 当我在查看 nhibernate 分析器时,我可以看到 begin transaction 语句,但它后面既没有提交也没有回滚。 更重要的是,即使我将 try-catch 块放在那里并在 catch 中显式执行 Rollback,我的测试仍然失败。 我认为测试环境存在一些问题,但对我来说一切都很好。

有什么想法吗?

编辑:我添加了重要的 try-catch 块(一开始我已经简化了太多代码)。

【问题讨论】:

【参考方案1】:

如果在 NH 将更改刷新到数据库之前发生异常,并且如果您继续使用该会话而不驱逐/清除对象并且由于某种原因稍后发生刷新,则更改仍将保留,因为对象根据 NHibernate 仍然很脏。回滚事务时应立即关闭会话以避免此类问题。

另一种说法:回滚不会回滚您对持久实体所做的内存更改。

此外,如果会话是常规会话,则不需要调用 Save(),因为 NH 已跟踪该实例。

【讨论】:

感谢您的回答。你写的是真的,但在实际代码中,Foo() 中有 try-catch 块,我忘了在开头写。抱歉,是我的错!所以我仍然不知道问题出在哪里。 @Przecinek 我查看了您更新的代码。 Foo() 中的 try-catch 具有吞噬异常的效果,这意味着 When() 将继续执行,就好像什么都没发生一样。由于调用 Foo() 之后是调用 session.Flush(),因此您在 Foo() 中所做的更改现在将在调用 Clear() 之前推送到数据库。这就是我上面的回答所描述的情况。

以上是关于休眠事务和单元测试的主要内容,如果未能解决你的问题,请参考以下文章

SpringMVC中单元测试中事务的使用

SpringMVC中单元测试中事务的使用

如何在 MySql 中对事务提交超时进行单元测试?

SpringBoot实现单元测试时回滚事务

SpringBoot实现单元测试时回滚事务

App Engine Java JDO 中的单元测试 XG 跨组事务