用Sqlite的内存数据库对nhibernate进行单元测试
针对数据访问代码的单元测试处在一个尴尬的位置上,如果操作不是针对真实的数据库执行的,就无法捕获数据库特定的错误,比如 sql 语句语法是否正确,操作是否违反了数据库约束,事务是否正确提交。并且,测试之间应该是隔离的,一个测试不能影响另一个测试的数据,就是说,每个测试运行之前都要重建表结构,重新安装测试数据。在一个真实的数据库上执行这些操作会让测试成为老牛破车。
所幸的是Sqlite提供了内存数据库,避免磁盘IO可以带来性能提升。内存数据库有一个非常重要的特点:即数据库仅在连接打开的时候存在,一旦连接关闭,数据库随即消失。这正是我们想要的,运行测试的步骤如下:
1,在 [TestInitialize] 方法中打开 Session,创建表结构,安装测试数据。默认情况下,Sqlite的Unicode字符串比较是区分大小写的,所以,创建表结构的时候要为 TEXT 列指定 COLLATE NOCASE。
2,运行测试
3,在 [TestCleanup] 方法中关闭 Session,这将导致底层的连接关闭,内存数据库消失。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | [TestClass] public class MyTest { [AssemblyInitialize] public static void InitAssembly(TestContext testContext) { NHibernateHelper.Init(); } [AssemblyCleanup] public static void CleanupAssembly() { NHibernateHelper.CloseSessionFactory(); } protected ISession Session { get ; private set ; } [TestInitialize()] public void MyTestInitialize() { try { // 1 打开 Session Session = NHibernateHelper.OpenSession(); // 2 创建表 NHibernate.Tool.hbm2ddl.SchemaExport export = new NHibernate.Tool.hbm2ddl.SchemaExport(NHibernateHelper.Configuration); export.SetDelimiter( ";" ); StringWriter sw = new StringWriter(); export.Execute( false , false , false , Session.Connection, sw); using (IDbCommand cmd = Session.Connection.CreateCommand()) { // 替换字段定义语句 cmd.CommandText = Regex.Replace(sw.ToString(), @"\s+TEXT\s+" , " TEXT COLLATE NOCASE " , RegexOptions.IgnoreCase | RegexOptions.Compiled); cmd.ExecuteNonQuery(); } // 3 创建测试数据 using (ITransaction tx = Session.BeginTransaction()) { Role role = new Role(); role.Name = "admins" ; Session.Save(role); tx.Commit(); } // 4 清除 Session 缓存 Session.Clear(); } catch (Exception ex) { // 如果发生异常,则 TestCleanup 不会执行,因此在这里回收资源 if (Session != null ) { Session.Close(); } throw ; } } [TestCleanup()] public void MyTestCleanup() { Session.Close(); Session = null ; } [TestMethod] public void MyTestMethod() { using (ITransaction tx = Session.BeginTransaction()) { Role role = Session.Query<Role>().FirstOrDefault(x => x.Name == "admins" ); Assert.IsNotNull(role); tx.Commit(); } } } |
NHibernate 配置,注意 connection.release_mode 属性一定要设为 on_close
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | < hibernate-configuration xmlns="urn:nhibernate-configuration-2.2"> < bytecode-provider type="null"/> < reflection-optimizer use="false"/> < session-factory > < property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</ property > < property name="connection.driver_class">NHibernate.Driver.SQLite20Driver</ property > < property name="connection.connection_string"> data source=:memory: </ property > < property name="dialect">NHibernate.Dialect.SQLiteDialect</ property > < property name="connection.release_mode">on_close</ property > < property name="hbm2ddl.keywords">none</ property > < property name="current_session_context_class">managed_web</ property > < property name="show_sql">false</ property > < property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</ property > < property name="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</ property > < mapping assembly="WuTong"/> </ session-factory > </ hibernate-configuration > |
参考链接:
分类:
代码收藏
, NHibernate
标签:
nhibernate
, sqlite
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?