NHibernate Load vs. Get行为用于测试

Ber*_*ryl 2 nhibernate unit-testing

在简单的测试中,我可以通过它的Id是否不再是默认值来断言对象是否已被持久化.但是删除一个对象并想要检查对象及其子对象是否真的不在数据库中,对象Id仍将保存在其保存的值中.

所以我需要转到db,我想要一个帮助器断言来使测试更具可读性,这就是问题的来源.我喜欢使用Load来保存db调用的想法,但我想知道是否随后的异常会破坏会话.

我想,下面是两个断言的外观.你会用哪个?

干杯,
Berryl

得到

public static void AssertIsTransient<T>(this T instance, ISession session)
    where T : Entity
{
    if (instance.IsTransient()) return; 

    var found = session.Get<T>(instance.Id);
    if (found != null) Assert.Fail(string.Format("{0} has persistent id '{1}'", instance, instance.Id));
}
Run Code Online (Sandbox Code Playgroud)

加载

public static void AssertIsTransient<T>(this T instance, ISession session)
    where T : Entity
{
    if (instance.IsTransient()) return; 

    try
    {
        var found = session.Load<T>(instance.Id);
        if (found != null) Assert.Fail(string.Format("{0} has persistent id '{1}'", instance, instance.Id));
    }
    catch (GenericADOException)
    {
        // nothing
    }
    catch (ObjectNotFoundException)
    {
        // nothing
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑

在任何一种情况下,我都会在新会话中进行提取(获取或加载),从执行保存或删除的会话中取消状态.

我试图测试级联行为,而不是测试NHib删除东西的能力,但也许我在考虑这个或者有一个我没有想到的更简单的方法.

Gob*_*lin 6

您在"加载"部分中的代码将始终命中Assert.Fail,但永远不会抛出异常,因为Load<T>它将返回代理(具有Id属性集 - 或者从第1级缓存填充)而不会访问数据库 - 即.如果您在已删除的实体上访问除Id属性之外的属性,则ISession.Load将失败.

至于你的"获取"部分 - 我可能会弄错,但我认为如果你删除一个会话中的实体 - 后来尝试在同一个会话中使用.Get - 你将获得一级缓存中的一个 - 并且再次不返回null.

有关.Load和.Get的完整说明,请参阅此文章.

如果你真的需要查看它是否在你的数据库中 - 使用IStatelessSession - 或者启动一个子ISession(它将有一个空的一级缓存.

编辑:我想到了一个更大的问题 - 在提交事务时(默认情况下刷新会话时)将首先删除您的实体 - 所以除非您手动刷新会话(不推荐),否则您仍然会在数据库中使用它.

希望这可以帮助.