Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通过nhibernate对数据库查询进行单元测试_C#_Database_Unit Testing_Nhibernate - Fatal编程技术网

C# 通过nhibernate对数据库查询进行单元测试

C# 通过nhibernate对数据库查询进行单元测试,c#,database,unit-testing,nhibernate,C#,Database,Unit Testing,Nhibernate,我需要为从数据库加载数据的方法创建一个单元测试。我在研究单元测试和数据库,大多数文章都告诉你应该模拟数据库。但是,该方法基本上是从数据库加载对象,并通过SQL执行一些限制 因此,我想测试的是实际的数据库查询是否成功,因此我认为不能模拟数据库 我正在使用NHibernate作为我的ORM,并且正在使用QueryOver构建查询。我发现对数据库进行单元测试非常困难,因为数据库处于不一致的状态。你有什么想法/方法来做这样的测试吗 这是我想进行单元测试的特定方法: public IEnumerable&

我需要为从数据库加载数据的方法创建一个单元测试。我在研究单元测试和数据库,大多数文章都告诉你应该模拟数据库。但是,该方法基本上是从数据库加载对象,并通过SQL执行一些限制

因此,我想测试的是实际的数据库查询是否成功,因此我认为不能模拟数据库

我正在使用NHibernate作为我的ORM,并且正在使用
QueryOver
构建查询。我发现对数据库进行单元测试非常困难,因为数据库处于不一致的状态。你有什么想法/方法来做这样的测试吗

这是我想进行单元测试的特定方法:

public IEnumerable<IArticlePanel> LoadPanelsApplicableToArticle(ArticleModule.IArticle article, Enums.ARTICLE_PANEL_LOCATION location)
   {
       CS.General_v3.Util.ContractsUtil.RequiresNotNullable(article, "Article must not be null");

       var articleList = Modules.Factories.ArticleFactory.GetAllParentsForAnArticle(article).ToList();
       articleList.Add(article);

       var q = GetQuery();
       q = q.WhereRestrictionOn(x => x.Article).IsInG(articleList.ConvertAll<long>(x => ((IBaseDbObject)x).ID));
       q = q.Where(x => x.Location == location);
       return FindAll(q);
 }
public IEnumerable LoadPanelsapplicable to article(ArticleModule.IArticle article,Enums.article\u PANEL\u LOCATION)
{
CS.General_v3.Util.ContractsUtil.RequiresNotNullable(第条,“第条不得为空”);
var articleList=Modules.Factories.ArticleFactory.GetAllParentsForAnArticle(article.ToList();
添加(第条);
var q=GetQuery();
q=q.WhereRestrictionOn(x=>x.Article).IsInG(articleList.ConvertAll(x=>((ibasedbobobject)x.ID));
q=q.Where(x=>x.Location==Location);
返回FindAll(q);
}

过去,当我需要对数据库进行单元测试时,我通常使用。您基本上是在内存中设置SQLite数据库,然后配置NHibernate(依赖项注入,或者按照您的意愿)以连接到SQLite,而不是普通的数据库。几乎所有查询都应该能够正确运行


如果您需要强大的DateTime支持,SQLite可能会让您失望(请参阅Ayende的文章)。在这种情况下,您可以使用任何嵌入式数据库。我建议设置一个RAMDisk并将嵌入式数据库放在该磁盘上,这样它仍然在内存中运行。

我个人使用了真实数据库来进行集成测试。我觉得这是最接近实际生产场景的。我们的开发团队目前没有从nhibernate映射生成数据库,因此映射和数据库之间存在一些不一致(例如数据库默认值等)。如果您是从nhibernate生成模式,SQLLite可能是您的正确路径。但如果你不是,我个人觉得最好针对真实数据库编写这些测试

我的集成测试将插入测试所需的数据,并在测试后删除数据。此方法的唯一缺陷是,您必须确保在测试结束后删除所有数据,否则可能会影响其他测试。我发现这对我们公司来说是一个可行的解决方案,而且非常有帮助。我们有一个专门的数据库,只用于单元测试

下面是我的一个测试示例:

[TestMethod]
public void Test_NHibernate_Query()
{
    //Create the data in the database necessary to test my nhibernate query
    CreateDataForUnitTest();

    IInventoryRepository target = new InventoryRepository(nhibernateSession);

    IList<InventoryView> inventoryRecords = target.GetContainerInventory(productId);

    Assert.AreEqual(1, inventoryRecords.Count);
}

[TestCleanup]
public void CleanUp()
{
    DeleteAll<Order>();
    DeleteAll<Company>();
}

public void DeleteAll<T>() where T : Entity
{
    NHibernate.ISession session = SessionFactory.GetCurrentSession();

    using (NHibernate.ITransaction tran = session.BeginTransaction())
    {
        IList<T> items = session.CreateCriteria<T>()
            .List<T>();

        foreach (T p in items)
        {
            session.Delete(p);
        }

        tran.Commit();
    }
}
[TestMethod]
公共无效测试\u NHibernate\u查询()
{
//在数据库中创建测试我的nhibernate查询所需的数据
CreateDataForUnitTest();
IIInventoryRepository目标=新的InventoryRepository(nhibernateSession);
IList inventoryRecords=target.GetContainerInventory(productId);
Assert.AreEqual(1,inventoryRecords.Count);
}
[测试清理]
公共空间清理()
{
DeleteAll();
DeleteAll();
}
public void DeleteAll(),其中T:Entity
{
NHibernate.ISession session=SessionFactory.GetCurrentSession();
使用(NHibernate.ITransaction tran=session.BeginTransaction())
{
IList items=session.CreateCriteria()
.List();
foreach(项目中的TP)
{
删除(p);
}
trans.Commit();
}
}

我们使用NCommon的IRepository。然后我们使用InMemoryRepository进行单元测试。非常灵活、快速且易于使用。

切换到sqlite数据库进行测试。这就是我目前的工作方式。但是,有时由于依赖关系,在之后清理并使数据库恢复到一致状态并不容易。我想更多地了解一下是否有我目前不知道的选项,但是这似乎是解决我的问题的最好方法。如果您使用mssql,如果一致状态意味着为空,那么可能有一种简单的方法可以使数据库恢复一致状态。实际上,我可能会考虑这样做。这种方法的问题是,数据库中必须有一些设置和其他值,因为某些初始化代码等依赖于它们。因此,我需要从头开始重新创建一个SQLite,填充这些设置等。我曾尝试过这样做,但有时它很难维护。如果您遇到的情况是,对数据库本身进行单元测试非常关键,然后,投入一点额外的时间来编写SQLite数据库创建和定制代码通常不是什么大问题。我从来没有遇到过这样的情况:需要一天以上的时间来编写初始化数据库所需的所有内容,然后在将来的所有单元测试中都完成了。如果不值得花那么多时间,那么可能根本不值得担心数据层的单元测试。