如何解决在内存中的SQLite db上使用NHibernate测试时出现随机错误
|| 我有一个系统,在收到消息后-将其入队(写到表中),另一个进程将轮询数据库并将其出队以进行处理。在我的自动测试中,我已经在同一过程中合并了这些操作,但是无法(从概念上)合并这两个操作的NH会话。 自然地-问题出现了。 我已经阅读了有关使sqlite-InMemory-NHibernate组合在测试环境中工作的一切知识,但是由于“没有此类表”错误,我现在遇到了随机失败的测试。明确地说-“随机”表示具有相同确切配置和代码的相同测试有时会失败。 我有以下sqlite配置:return sqliteConfiguration
.Standard
.ConnectionString(x => x.Is(\"Data Source=:memory:; Version=3; New=True; Pooling=True; Max Pool Size=1;\"))
.Raw(NHibernate.Cfg.Environment.ReleaseConnections,\"on_close\");
在测试(每次测试)开始时,我获取\“ static \”会话提供程序,并请其将现有的数据库清除干净,并重新创建模式:
public void PurgeDatabaSEOrCreateNew()
{
using (var session = GetNewSession())
using (var tx = session.BeginTransaction())
{
PurgeDatabaSEOrCreateNew(session);
tx.Commit();
}
}
private void PurgeDatabaSEOrCreateNew(ISession session)
{
//http://ayende.com/Blog/archive/2009/04/28/nhibernate-unit-testing.aspx
new SchemaExport(_Configuration)
.Execute(false,true,false,session.Connection,null);
}
因此,是的,它在不同的会话上,但是连接是在sqlite上建立的,因此我创建的下一个会话将看到生成的架构。但是,尽管大多数情况下它都起作用,但有时以后的“入队”操作将失败,因为它看不到我收到的消息的表。
另外-这似乎在每次测试套件运行中最多发生一两次。并非所有测试都失败了,只有第一个测试失败了(有时还会失败。有时不确定是否是第二个)。
自然,最糟糕的部分是随机性。我已经告诉自己我已经修复了好几次,只是因为它只是“停止了失败”。随意地。
在TestDriven.NET 32b进项和NUnit控制台32b进程上,在FW4.0,System.Data.sqlite x86版本,Win7 64b和2008R2(总共三台不同的机器),配置有FNH的NH2.1.2上会发生这种情况。
救命?
解决方法
嗨,我很确定我和您有同样的问题。每个集成测试我打开和关闭多个会话。在深入研究了SQLite连接池并进行了一些我自己的尝试之后,我得出以下结论:
SQLite池代码使用WeakReferences来缓存连接,这不是缓存的最佳选择,因为当没有正常(强)的连接引用且GC运行时,将清除对连接的引用。由于您无法预测GC的运行时间,因此可以解释“随机性”。尝试在关闭一个会话与打开另一个会话之间添加“ 2”,您的测试将始终失败。
我的解决方案是在打开的会话之间自己缓存连接,如下所示:
public class BaseIntegrationTest
{
private static ISessionFactory _sessionFactory;
private static Configuration _configuration;
private static SchemaExport _schemaExport;
// I cache the whole session because I don\'t want it and the
// underlying connection to get closed.
// The \"Connection\" property of the ISession is what we actually want.
// Using the NHibernate SQLite Driver to get the connection would probably
// work too.
private static ISession _keepConnectionAlive;
static BaseIntegrationTest()
{
_configuration = new Configuration();
_configuration.Configure();
_configuration.AddAssembly(typeof(Product).Assembly);
_sessionFactory = _configuration.BuildSessionFactory();
_schemaExport = new SchemaExport(_configuration);
_keepConnectionAlive = _sessionFactory.OpenSession();
}
[SetUp]
protected void RecreateDB()
{
_schemaExport.Execute(false,true,false,_keepConnectionAlive.Connection,null);
}
protected ISession OpenSession()
{
return _sessionFactory.OpenSession(_keepConnectionAlive.Connection);
}
}
我的每个集成测试都继承自此类,并调用OpenSession()来获取会话。由于[SetUp]属性,在每次测试之前NUnit都会调用RecreateDB。
希望这对您或其他收到此错误的人有所帮助。
,唯一会想到的是,您在测试后会随机打开会话。打开另一个ISession之前,必须确保已将其关闭。如果您没有使用using()语句或手动调用Dispose(),则该会话可能仍处于活动状态,从而导致这些随机异常。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。