Я настроил несколько модульных тестов SQLite в памяти для своей базы данных Fluent NHibernate, которая выглядит следующим образом. Работает нормально. (С использованием NUnit
)
namespace Testing.Database {
/// <summary>
/// Represents a memory only database that does not persist beyond the immediate
/// testing usage, using <see cref="System.Data.SQLite"/>.
/// </summary>
public abstract class InMemoryDatabase : IDisposable {
/// <summary>
/// The configuration of the memorized database.
/// </summary>
private static Configuration Configuration { get; set; }
/// <summary>
/// The singleton session factory.
/// </summary>
protected static ISessionFactory SessionFactory { get; set; }
/// <summary>
/// The current session being used.
/// </summary>
protected ISession Session { get; set; }
protected InMemoryDatabase() {
SessionFactory = CreateSessionFactory();
Session = SessionFactory.OpenSession();
BuildSchema(Session);
}
/// <summary>
/// Construct a memory based session factory.
/// </summary>
/// <returns>
/// The session factory in an SQLite Memory Database.
/// </returns>
private static ISessionFactory CreateSessionFactory() {
return FluentNHibernate.Cfg.Fluently.Configure()
.Database(FluentNHibernate.Cfg.Db.SQLiteConfiguration
.Standard
.InMemory()
.ShowSql())
.Mappings(mappings => mappings.FluentMappings.AddFromAssemblyOf<Data.Mappings.AspectMap>())
.ExposeConfiguration(configuration => Configuration = configuration)
.BuildSessionFactory();
}
/// <summary>
/// Builds the NHibernate Schema so that it can be mapped to the SessionFactory.
/// </summary>
/// <param name="Session">
/// The <see cref="NHibernate.ISession"/> to build a schema into.
/// </param>
private static void BuildSchema(ISession Session) {
var export = new NHibernate.Tool.hbm2ddl.SchemaExport(Configuration);
export.Execute(true, true, false, Session.Connection, null);
}
/// <summary>
/// Dispose of the session and released resources.
/// </summary>
public void Dispose() {
Session.Dispose();
}
}
}
Итак, теперь, чтобы использовать его, я просто наследую InMemoryDatabase
и добавляю свои методы Test, вот так.
[TestFixture]
public class PersistenceTests : InMemoryDatabase {
[Test]
public void Save_Member() {
var member = // ...;
Session.Save(member); // not really how it looks, but you get the idea...
}
}
Моя проблема не в том, что это не работает. Оно делает. Но если у меня есть два теста в одном классе, которые проверяют похожие данные, например ...
Username_Is_Unique()
, а затем Email_Is_Unique()
. Опять не настоящие тесты, но это хороший пример.
[Test]
public void Username_Is_Unique(){
var user = new User {
Name = "uniqueName"
Email = "uniqueEmail"
};
// do some testing here...
}
[Test]
public void Email_Is_Unique(){
var user = new User {
Name = "uniqueName"
Email = "uniqueEmail"
};
// do some testing here...
}
Я понимаю, что это очень плохие тесты. Это не настоящие тесты, я просто привожу пример.
В обоих случаях я бы создал макет User
или Member
или что-то еще и отправил бы его в базу данных.
Первый работает нормально, но, поскольку база данных находится в памяти (что имеет смысл, поскольку я это сказал), вторая - нет. По сути, модульные тесты не отражают реальных ситуаций, потому что каждый тест стоит сам по себе. Но когда они запускаются последовательно в пакете, он ведет себя так, как должен в реальном мире (я полагаю, это отчасти хорошо)
Что я хочу сделать, это очистить базу данных в памяти после каждого метода. Поэтому я придумал простой способ сделать это, повторив конструктор. Это относится к классу InMemoryDatabase
.
protected void Restart() {
SessionFactory = CreateSessionFactory();
Session = SessionFactory.OpenSession();
BuildSchema(Session);
}
Итак, теперь в каждом методе моего класса наследования я вызываю Restart()
перед тем, как приступить к тестированию.
Я чувствую, что это не намеченный или эффективный способ решения моей проблемы. Кто-нибудь может предложить лучшее решение?
Если это имеет какое-либо отношение, я использую Fluent nHibernate
для постоянства и Telerik JustMock
для моего Пересмешивания - но для моей базы данных мне еще не нужно насмехаться.