NHibernate单元测试模拟/内存数据库

时间:2013-12-21 16:05:06

标签: c# unit-testing nhibernate fluent-nhibernate mocking

我正在尝试学习如何模拟我的通用存储库,以便我可以对我的所有服务进行单元测试。

我使用NHibernate Fluent来处理数据访问和Ninject的依赖(我对测试没兴趣)

我的存储库界面如下所示:

public interface IRepository<TEntity>  where TEntity : class 
{
    IQueryable<TEntity> GetAll();
    TEntity Get(int key);
    void Insert(TEntity entity);
    void Update(TEntity entity);
    void Delete(int id);
}

实际存储库看起来像:

public class GenerRepository<TEntity> : IRepository<TEntity>where TEntity : Entity
{
    protected ISession Session{get { return NHibernateHelper.OpenSession(); }}
    public IQueryable<TEntity> GetAll(){return Session.Query<TEntity>();}
    public TEntity Get(int key){return Session.Get<TEntity>(key);}
    public void Insert(TEntity entity){Session.Save(entity);}
    public void Update(TEntity entity){Session.Update(entity);}
    public void Delete(int id){Session.Delete(Session.Load<TEntity>(id));}
}

我的所有服务都执行以下操作,将创建的存储库放入其中并使用它。

我已经阅读了很多关于如何做到这一点的文章,但没有一篇很简单或很好解释。所以在创建测试通用存储库或甚至模拟它之间的任何建议。我也有兴趣创建一个内存数据库但是如何在我的测试项目中为流畅的nhibernate设置配置而不在我的实际项目中编辑代码?

是否可以将通用存储库命中为Tentity列表而不是数据库或内存数据库。

感谢阅读并期待这些建议。

3 个答案:

答案 0 :(得分:6)

我必须同意Radim的观点,即在大多数情况下通过模拟nhibernate功能来测试nhibernate代码,而不是你想做什么。

除非你想测试基于你通过nhibernate检索的数据的复杂业务逻辑,否则这很好。

但是要测试您的映射,数据检索和持久性是否正常,您必须针对真实数据库进行测试。

如果您定位MSSQL Server,我不会使用其他类型的数据库。相反,SQL Express具有真实服务器的所有功能。 MSSQL Express可以选择与本地DB一起安装。这将允许您通过连接字符串加载mdf文件,这将或多或少地实例化MSSQL Server的实例......

我用它进行集成测试,效果非常好。

  1. 在单元测试项目中创建数据库文件
  2. 根据你的模型(代码优先/ db优先)让nhibernate创建方案,否则简单地将方案填充到该数据库文件中
  3. 将文件添加到测试设置的部署项中,以便将文件复制到测试目标目录
  4. 生成使用复制的数据库文件的连接字符串。 连接字符串示例:Data Source=(LocalDB)\v11.0;AttachDbFileName=[whateverthepathis]\DatabaseFileName.mdf;InitialCatalog=DatabaseName;Integrated Security=True;MultipleActiveResultSets=True
  5. 运行测试
  6. 这样你的测试每次都会运行一个空的数据库,你将拥有可重现的集成测试,而不需要真正的服务器,你必须每次都创建一个数据库或重置它...

答案 1 :(得分:5)

我的回答应该/可能是一个评论,也许吧。因为我想告诉你:不要这样做。不要浪费时间来创建从持久性返回的数据。不要花时间:从客户端获取数据并将它们放入内存中的虚拟数据库中。

您需要确保您的服务(使用存储库)可以真正序列化/呈现真实数据。并反序列化/坚持改变。这确实需要真实的数据。

而是花一些时间来创建脚本,这将填充测试数据。您可以在测试中获得的数据:执行业务验证时,服务数据序列化 ......

另请看这里:Ayende: NHibernate Unit Testing。提取物:

  

使用NHibernate时,我们通常只想测试三件事,   属性是持久的,级联按预期工作   查询返回正确的结果。为了做所有这些,我们   通常不得不与真实的数据库交谈,试图伪装其中任何一个   在这个水平上是徒劳的,并且会变得非常复杂。

注意:前一段时间,我们曾经在事务Begin()Rollback()中包装所有测试。哪个看起来不错。但是我们意识到,很多东西 - 因为缺少Flush()调用 - 没有被完全测试(例如设置为非null)。

答案 2 :(得分:4)

有几种方法可以实现这一目标,

  1. 使用真实数据库进行测试,使用脚本来设置和恢复数据库,但是使用这种方法,当数据库发生变化时,创建和维护这些脚本需要花费时间和精力

  2. 使用真实数据库,并使用事务范围进行测试(启动事务持久化,并进行测试,一旦完成所有操作仅回滚事务),这是一个非常好的方法,我使用它来实现一个大型项目。然而,一个问题是运行测试需要花费大量时间(我有大约3500次测试,所有测试总共需要40分钟)

  3. 使用虚假存储库(具有实体的内部列表)进行业务逻辑测试,并使用实际存储库来验证映射。这种方法需要额外的努力来创建和维护虚假存储库。可以在假存储库上执行在实际存储库上执行的相同测试,以验证伪造是否正常工作。使用这种方法,测试执行会更快。