由于Enterprise Library,NUnit测试失败

时间:2012-06-06 21:37:04

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

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

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

难道你不自豪我终于到了吗?!

这是我得到的错误

  

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

我已经将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在一起。

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

2 个答案:

答案 0 :(得分:4)

同意@Jesse关于模拟依赖关系。如果你没有隔离sut那么它不是单元测试。 (建议阅读Art of UnitTesting

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

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

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

答案 1 :(得分: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时,您的测试模拟就会启动并返回您的预期数据。