SQLite のインメモリ データベースを使用して、SQLite の'Shared Cache' のサポートを使用することで、テストごとにスキーマを再構築する必要がなくなりました。これにより、インメモリ データベースを接続間で共有できます。
AssemblyInitializeで次のことを行いました(MSTest を使用しています)。
次の接続文字列で SQLite を使用するように NHibernate (Fluently) を構成します。
FullUri=file:memorydb.db?mode=memory&cache=shared
その構成を使用して、hbm2ddl を作成します。SchemaExportオブジェクトを作成し、別の接続で実行します (ただし、同じ接続文字列を使用します)。
- AssemblyCleanupまで、その接続を開いたままにし、静的フィールドによって参照されます。その時点で、接続は閉じられて破棄されます。これは、SQLite がまだ必要であることを認識し、片付けを避けるために、少なくとも 1 つのアクティブな接続をインメモリ データベースに保持する必要があるためです。
各テストが実行される前に、新しいセッションが作成され、最後にロールバックされるトランザクションでテストが実行されます。
アセンブリ レベルのテスト コードの例を次に示します。
[TestClass]
public static class SampleAssemblySetup
{
private const string ConnectionString = "FullUri=file:memorydb.db?mode=memory&cache=shared";
private static SQLiteConnection _connection;
[AssemblyInitialize]
public static void AssemblyInit(TestContext context)
{
var configuration = Fluently.Configure()
.Database(SQLiteConfiguration.Standard.ConnectionString(ConnectionString))
.Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.Load("MyMappingsAssembly")))
.ExposeConfiguration(x => x.SetProperty("current_session_context_class", "call"))
.BuildConfiguration();
// Create the schema in the database
// Because it's an in-memory database, we hold this connection open until all the tests are finished
var schemaExport = new SchemaExport(configuration);
_connection = new SQLiteConnection(ConnectionString);
_connection.Open();
schemaExport.Execute(false, true, false, _connection, null);
}
[AssemblyCleanup]
public static void AssemblyTearDown()
{
if (_connection != null)
{
_connection.Dispose();
_connection = null;
}
}
}
そして、各単体テスト クラス/フィクスチャの基本クラス:
public class TestBase
{
[TestInitialize]
public virtual void Initialize()
{
NHibernateBootstrapper.InitializeSession();
var transaction = SessionFactory.Current.GetCurrentSession().BeginTransaction();
}
[TestCleanup]
public virtual void Cleanup()
{
var currentSession = SessionFactory.Current.GetCurrentSession();
if (currentSession.Transaction != null)
{
currentSession.Transaction.Rollback();
currentSession.Close();
}
NHibernateBootstrapper.CleanupSession();
}
}
リソース管理が改善される可能性があることは認めますが、これらは結局のところ単体テストです (改善の提案を歓迎します!)。