【问题标题】:NUnit tests fail due to Enterprise LibraryNUnit 测试因企业库而失败
【发布时间】:2012-06-10 23:13:40
【问题描述】:

我在这里看到了几个处理类似问题的问题,但没有一个对我有帮助。

我在 MVC 3 项目中使用 NUnit 和 VS 2010。 我有一个测试项目,正在编写我的第一个测试 Evar! :-)

你不为我终于做到了吗?!

这是我遇到的错误

Microsoft.Practices.ServiceLocation.ActivationException:激活 尝试获取数据库类型的实例时发生错误,键 “我的连接”----> Microsoft.Practices.Unity.ResolutionFailedException:解决 依赖失败,类型 = “Microsoft.Practices.EnterpriseLibrary.Data.Database”,名称 = “我的连接”。异常发生时:解决时。例外是: InvalidOperationException - 无法构造类型 Database。 您必须配置容器以提供此值。

我已经为 web.config 配置了所有这些,并且当不在测试中运行时数据完美返回,所以我知道不是配置正在死去,它只是在与 NUnit 一起使用时死去。

这是我的连接信息:

<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
...
<dataConfiguration defaultDatabase="MyConnection" />
<connectionStrings>
<add name="MyConnection" connectionString="Data Source=MyServerName;Initial Catalog=MyDB;user id=MyUser;password=MyPassword"
  providerName="System.Data.SqlClient" />
</connectionStrings>

我已经使用 NuGet 安装了 DaaB,并且还做了一个干净的手动参考。无论哪种方式,数据在正常使用中加载良好,但在测试中它在这一行死亡:

var database = DatabaseFactory.CreateDatabase("MyConnection");

在这个方法中

public IEnumerable<SchoolSearchResultsDTO> Find(SchoolSearchInputDTO dto) {
    List<SchoolSearchResultsDTO> fullList;
    var database = DatabaseFactory.CreateDatabase("MyConnection");
    using (var command = database.GetStoredProcCommand("dbo.usp_School_SearchBySchoolName")) {
        database.AddInParameter(command, "@I_strSchoolName", DbType.String, dto.SearchTerm);
        database.AddInParameter(command, "@I_intNumberOfRecords", DbType.Int32, dto.MaxSearchResults);
        using (var reader = database.ExecuteReader(command)) {
            fullList = new List<SchoolSearchResultsDTO>();
            while (reader.Read()) {
                var fullRecord = new SchoolSearchResultsDTO();
                fullRecord.SchoolID = reader.GetInteger("SchoolId");
                fullRecord.SchoolName = reader.GetString("SchoolName");
                fullRecord.IsDetailedDisplayMode = reader.GetBoolean("IsDetailedDisplayMode");
                fullList.Add(fullRecord);
            }
            reader.Close();
        }
    }
    return fullList;
}

所有其他帖子都谈到了错误配置等。我很确定我的配置正确,否则我不会在正常使用情况下获得数据。所以它必须与 NUnit 和 DaaB 一起使用。

有什么好主意吗? :-) 谢谢大家!

【问题讨论】:

    标签: asp.net-mvc-3 unit-testing c#-4.0 nunit enterprise-library


    【解决方案1】:

    同意@Jesse 关于模拟依赖的观点。如果您不隔离 sut 那么它不是单元测试。 (推荐阅读Art of UnitTesting

    因此,您可以说您正在编写集成测试。

    如果不查看您的确切设置,就很难判断问题所在。你提到的一件事是你已经“配置了你的web.config”。

    但是您是否在测试项目中设置了配置文件?配置将从您的单元测试项目加载,而不是 MVC 项目。

    【讨论】:

    • 很好的信息!谢谢!我从来没有真正想过我的测试项目需要任何特殊的配置。我想我的尝试仍然在这里挣扎。
    • 将 app.config 添加到测试项目修复了它 :-) 感谢您的信息。顺便说一句,我有这本书,还没有开始,但昨天刚刚在 TekPub 上开始了 TDD 硕士课程(由本书的作者 Roy Osherove 编写),并且一直在关注,直到我挂断了这本书。谢谢你的腿! :-)
    • 好东西,TDD 将是您编码方式的最大变化。在最初的几个障碍之后,我想你会发现它会让你更有效率。
    • Uncle bob 在这里有一段关于 TDD 的精彩片段,展示了保龄球应用程序。这有点做作,但鲍勃叔叔是一个传奇。 cleancoders.com/codecast/clean-code-episode-6-part-2/show
    • 是的,我读了两遍他的 Clean Code 书和 Clean Coder。几周前我开始看第一集,但还没有回来。任何人为的东西,我同意,它确实是,总是让我感到厌烦。我往往需要处理我正在处理的真实情况,否则我觉得我无法应用所学。
    【解决方案2】:

    通常最好避免在单元测试中直接访问数据库。我建议留出一些时间来阅读有关创建有价值且可靠的单元测试的模拟。通过模拟,您可以将模拟服务层注入到相关控制器中,该服务层将被设置为返回您预期的数据库数据。

    在您的测试中,您将创建该服务层的模拟。例如使用moq(我的模拟框架偏好):

    // create your expected data
    var YourExpectedData = new IList<SchoolSearchResultsDTO>();
    
    // .... add your expected information
    
    //create & setup mock
    var _service = new Mock<IYourService>();
    _service.Setup(service => service.Find(It.IsAny<SchoolSearchInputDTO>())).Returns(YourExpectedData);
    
    // create your controller
    var controller = new YourCountroller(_service.object())
    

    从这一点开始,您的单元测试非常简单。每当在各种代码中调用方法 find 时,您的测试模拟就会启动并返回您的预期数据。

    【讨论】:

    • 看,这就是我喜欢 SO 的原因!好的,所以我不知道。我只是假设我正在测试行为,而我期望的行为是返回数据并验证我得到了我所要求的。所以我不确定如何处理。在某些背景下,该应用程序只不过是一个 UI,它允许用户搜索学校并查看有关该学校的数据。没有业务逻辑,没有数据更新,在我看来,没有什么比“用户搜索输入是否返回了预期的结果?”更需要测试的了。我看不出嘲讽会给我带来真正有用的信息。
    • 但正如 jflood 所说,这些类型的测试更多的是集成测试而不是单元测试。那正确吗?我是不是在浪费时间尝试使用这种应用程序进行测试?
    • 这正是 Mocking 的重点。模拟消除了数据库的依赖性。需要设置和维护一个测试数据库,以确保返回给测试的输入是有效的。通过模拟,您的“预期数据”始终是您设置的。这样,您可以确保您的测试功能不依赖于您的数据库。也就是说,如果您想探索一种利用您的数据库的集成类型测试方法,我会推荐:blog.codeville.net/2009/06/11/…
    • 太棒了,谢谢!我和我的经理一起讨论了这一切,他同意并假设我只是知道这一点。好吧,我没有。谢谢!我想我看到了曙光!我现在有了实现我的存储库接口并提供不会改变的测试数据的模拟,因此可以更准确地预测回归测试。
    猜你喜欢
    • 1970-01-01
    • 2023-01-20
    • 2016-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多