如何对NHibernate拦截器进行单元测试

本文关键字:单元测试 NHibernate | 更新日期: 2023-09-27 18:00:52

我有一个NHibernate拦截器,它覆盖Instanciate方法,并执行以下操作:

  • 如果要实例化的类继承了某个基类,则返回CastleDynamicProxy
  • 否则就讨好全班同学

虽然这听起来很简单(而且已经有效了(,但如果我能用单元测试来证明它的功能,我还是会感觉更好。

这是拦截器代码:

    public override object Instantiate(string entityTypeName, EntityMode entityMode, object id)
    {
        // Type resolution across Assembly borders
        Type type = TypeFinder.FindType(entityTypeName);
        if (type == null)
        {
            throw new Exception(string.Format("",entityTypeName));
        }
        bool isViewModel = (typeof(ViewModelBase).IsAssignableFrom(type));
        if (entityMode == EntityMode.Poco && isViewModel)
        {
            var instance = ProxyFactory.CreateProxy(type);
            SessionFactory.GetClassMetadata(entityTypeName).SetIdentifier(instance, id, entityMode);
            return instance;
        }
        return base.Instantiate(entityTypeName, entityMode, id);
    }

我可以成功地测试我的代理生成代码,但base.Instantiate总是返回null。这是我的测试代码(正如你所看到的,我甚至添加了一个真正的数据库,以防拦截器需要一个有效的会话(:

    private FluentConfiguration PrepareDataBase()
    {
        string connectionString = @"Data Source=test.sdf;";
        SqlCeEngine en = new SqlCeEngine(connectionString);
        en.CreateDatabase();
        FluentConfiguration fc = Fluently.Configure().Database(MsSqlCeConfiguration.Standard
                                                              .ConnectionString(c => c.Is(connectionString))
                                                              .ShowSql())
                                   .Mappings(x => x.FluentMappings.AddFromAssemblyOf<ViewModel>());
        new SchemaExport(fc.BuildConfiguration()).Create(true, true);
        return fc;
    }
    [TestMethod]  
    [DeploymentItem("System.Data.SqlServerCe.dll")]
    public void Test_Instantiate_WithNonViewModelBasedPoco_ReturnsInstance()
    {
        TypeFinder.RegisterAssembly(typeof(OtherPoco).Assembly);
        FluentConfiguration fc = PrepareDataBase();
        NhChangeNotificationInterceptor interceptor = new NhChangeNotificationInterceptor(); 
        ISession session = fc.BuildSessionFactory().OpenSession(interceptor);
        string instanceType = typeof(OtherPoco).FullName;
        object instance = interceptor.Instantiate(instanceType, EntityMode.Poco, null);
        Assert.AreEqual(typeof(OtherPoco).FullName, instance.GetType().FullName);
        Assert.IsFalse(typeof(ViewModelBase).IsAssignableFrom(instance.GetType()));
    }

我认为空标识符可能有问题,所以我保存了一条记录,并尝试添加它的Id,如下所示:

        NhChangeNotificationInterceptor interceptor = new NhChangeNotificationInterceptor(); 
        ISession session = fc.BuildSessionFactory().OpenSession(interceptor);
        using (ITransaction trx = session.BeginTransaction())
        {
            session.Save(new OtherPoco() { Id = 1 });
            session.Flush();
        }
        string instanceType = typeof(OtherPoco).FullName;
        object instance = interceptor.Instantiate(instanceType, EntityMode.Poco, 1);

但不会改变任何事情。知道我如何测试base.Instantiate吗?

如何对NHibernate拦截器进行单元测试

我不会尝试为此编写单元测试。拦截器与NH/数据库紧密耦合,最好为此编写集成测试。

不要试图测试代码行。相反,请测试您的功能。您已经说明了拦截器应该做什么("如果要实例化的类继承了某个基类,则返回CastleDynamicProxy,否则只初始化该类"(。测试一下!如果您以后想使用拦截器以外的其他技术来获得相同的结果,那么不应该强迫您修改测试。

所以不用调用拦截器。直接从测试中实例化,进行一些集成测试,验证它在从数据库获取数据时是否做了应该做的事情。