2010-03-17 129 views
2

我想单元测试一个DEPENDENT服务层,它允许我在不使用NUnit模拟的情况下执行CRUD操作。我知道这可能是不好的做法,但无论如何我都想尝试一下 - 即使测试需要运行一整夜。我的数据是使用NHibernate持久化的,我已经实现了一个“引导”数据库的小型库,我可以在[Setup]方法中使用它。我只是想知道是否有人做了类似的事情,以及引导数据库的最快方法是什么。我使用的是这样的:单元测试服务层 - NUnit,NHibernate

var cfg = new Configuration(); 
      cfg.Configure(); 
      cfg.AddAssembly("Bla"); 
      new SchemaExport(cfg).Execute(false, true, false); 

建立数据库模式。之后,我从一些Excel表中填充一些查找表。

任何反馈将非常感激。谢谢。

基督教

+2

外部资源?那些不再是单元测试你正在尝试实现,但集成测试。 – 2010-03-17 09:47:08

+0

好的,我知道。让我们叫它测试然后( - : – cs0815 2010-03-17 10:01:09

回答

2

Ayende在此blog post中有一个很好的示例。他的例子如下所示,我的评论。

由于配置创建起来很昂贵,因此每次测试运行时只创建一次。使用SQLite内存数据库是因为这是执行查询的最快方式。

public class InMemoryDatabaseTest : IDisposable 
{ 
    private static Configuration Configuration; 
    private static ISessionFactory SessionFactory; 
    protected ISession session; 

    public InMemoryDatabaseTest(Assembly assemblyContainingMapping) 
    { 
     if (Configuration == null) 
     { 
      Configuration = new Configuration() 
       .SetProperty(Environment.ReleaseConnections,"on_close") 
       .SetProperty(Environment.Dialect, typeof (SQLiteDialect).AssemblyQualifiedName) 
       .SetProperty(Environment.ConnectionDriver, typeof(SQLite20Driver).AssemblyQualifiedName) 
       .SetProperty(Environment.ConnectionString, "data source=:memory:") 
       .SetProperty(Environment.ProxyFactoryFactoryClass, typeof (ProxyFactoryFactory).AssemblyQualifiedName) 
       .AddAssembly(assemblyContainingMapping); 

      SessionFactory = Configuration.BuildSessionFactory(); 
     } 

     session = SessionFactory.OpenSession(); 

     new SchemaExport(Configuration).Execute(true, true, false, true, session.Connection, Console.Out); 
    } 

    public void Dispose() 
    { 
     session.Dispose(); 
    } 
} 

当使用这个,每个测试开始创建所需的数据。

public class BlogTestFixture : InMemoryDatabaseTest 
{ 
    public BlogTestFixture() : base(typeof(Blog).Assembly) 
    { 
    } 

    [Fact] 
    public void CanSaveAndLoadBlog() 
    { 
     object id; 

     using (var tx = session.BeginTransaction()) 
     { 
      id = session.Save(new Blog 
      { 
       AllowsComments = true, 
       CreatedAt = new DateTime(2000,1,1), 
       Subtitle = "Hello", 
       Title = "World", 
      }); 

      tx.Commit(); 
     } 

     session.Clear(); 


     using (var tx = session.BeginTransaction()) 
     { 
      var blog = session.Get<Blog>(id); 

      Assert.Equal(new DateTime(2000, 1, 1), blog.CreatedAt); 
      Assert.Equal("Hello", blog.Subtitle); 
      Assert.Equal("World", blog.Title); 
      Assert.True(blog.AllowsComments); 

      tx.Commit(); 
     } 
    } 
} 
2

当写这样集成测试,最重要的事情要记住,你还是应该

  • 自动化尽可能地(最好是所有),其中包括设置建立数据库并在使用后再次删除
  • 避免General Fixture反模式,这意味着每个测试用例都应该以空数据库开始,而我用Back Door Manipulation填写适当的行。

我在过去几次写了大约my own experiences with testing against databases

+0

谢谢,我会看看这个。 – cs0815 2010-03-17 10:41:20