使用 Fluent nHibernate 进行单元测试 - 删除每个测试可能性的数据
本文关键字:测试 可能性 数据 删除 nHibernate Fluent 单元测试 使用 | 更新日期: 2023-09-27 17:59:42
我已经为我的Fluent NHibernate数据库设置了一些内存SQLite单元测试,看起来像这样。它工作正常。(使用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
并添加我的测试方法,就像这样。
[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
用于我的模拟 - 但对于我的数据库内容,我还没有需要任何模拟。
您需要为每个测试删除并重新创建数据库。每个测试都应该相互独立。你可以做两件事,首先让你的测试使用设置方法(假设这里有NUnit,但其他人具有相同的功能(
[SetUp]
public void Setup()
{
// Create in memory database
Memdb = new InMemoryDatabase();
}
或者,可以将每个测试包装在数据库的 using 语句中。例如
[Test]
public void Test()
{
using(var db = new InMemmoryDatabase())
{
Do Some Testing Here
}
}