Ich konnte eine SQLite-In-Memory-Datenbank verwenden und vermeiden, dass ich das Schema für jeden Test neu erstellen musste, indem ich die SQLite-Funktion Unterstützung für 'Shared Cache' die es ermöglicht, eine In-Memory-Datenbank über mehrere Verbindungen hinweg gemeinsam zu nutzen.
Ich habe Folgendes getan AssemblyInitialize (Ich verwende MSTest):
-
Konfigurieren Sie NHibernate (Fluently) für die Verwendung von SQLite mit der folgenden Verbindungszeichenfolge:
FullUri=file:memorydb.db?mode=memory&cache=shared
-
Verwenden Sie diese Konfiguration, um ein hbm2ddl zu erstellen. SchemaExport Objekt, und führen Sie es auf einer anderen Verbindung aus (aber wieder mit derselben Verbindungszeichenfolge).
-
Lassen Sie diese Verbindung, auf die ein statisches Feld verweist, offen, bis AssemblyCleanup zu diesem Zeitpunkt wird es geschlossen und entsorgt. Das liegt daran, dass SQLite mindestens eine aktive Verbindung zur In-Memory-Datenbank benötigt, um zu wissen, dass sie noch benötigt wird, und um Aufräumarbeiten zu vermeiden.
Vor jedem Test wird eine neue Sitzung erstellt, und der Test läuft in einer Transaktion, die am Ende zurückgerollt wird.
Hier ist ein Beispiel für den Test-Assembler-Code:
[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;
}
}
}
Und eine Basisklasse für jede Unit-Test-Klasse/Fixture:
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();
}
}
Die Ressourcenverwaltung könnte verbessert werden, das gebe ich zu, aber es handelt sich schließlich um Unit-Tests (Verbesserungsvorschläge sind willkommen!).