Мне удалось использовать базу данных SQLite в памяти и избежать необходимости перестраивать схему для каждого теста с помощью поддержки SQLite для 'Shared Cache' , которая позволяет совместно использовать базу данных в памяти через соединения.
Я сделал следующее в AssemblyInitialize (я использую MSTest):
Сконфигурируйте NHibernate (свободно) для использования SQLite со следующей строкой подключения:
FullUri=file:memorydb.db?mode=memory&cache=shared
Используйте эту конфигурацию для создания объекта hbm2ddl. SchemaExport и выполните его на отдельном соединении (но снова с той же строкой соединения).
- Оставьте это соединение открытым и на него ссылается статическое поле до AssemblyCleanup , после чего оно закрывается и удаляется. Это связано с тем, что для SQLite требуется наличие хотя бы одного активного соединения в базе данных в памяти, чтобы знать, что оно все еще требуется, и избегать очистки.
Перед каждым тестом создается новый сеанс, и тест выполняется в транзакции, откат которой выполняется в конце.
Вот пример кода тестового уровня сборки:
[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();
}
}
Управление ресурсами может быть улучшено, я признаю, но это все-таки модульные тесты (рекомендуемые улучшения приветствуются!).