我已经阅读了有关单元测试的越来越多的内容,并决心将其投入工作。我用存储库模式,依赖项注入和EF挖出了一个用ASP.NET MVC编写的项目。我的第一个任务是对控制器进行单元测试。这是控制器要测试的代码段:
IUserRepository _userRepository;
IAttachmentRepository _attachmentRepository;
IPeopleRepository _peopleRepository;
ICountryRepository _countryRepository;
public UserController(IUserRepository userRepo, IAttachmentRepository attachRepo, IPeopleRepository peopleRepo, ICountryRepository countryRepo)
{
_userRepository = userRepo;
_attachmentRepository = attachRepo;
_peopleRepository = peopleRepo;
_countryRepository = countryRepo;
}
public ActionResult Details()
{
UserDetailsModel model = new UserDetailsModel();
foreach (var doc in _attachmentRepository.GetPersonAttachments(Globals.UserID))
{
DocumentItemModel item = new DocumentItemModel();
item.AttachmentID = doc.ID;
item.DocumentIcon = AttachmentHelper.GetIconFromFileName(doc.StoragePath);
item.DocumentName = doc.DocumentName;
item.UploadedBy = string.Format("{0} {1}", doc.Forename, doc.Surname);
item.Version = doc.VersionID;
model.Documents.Add(item);
}
var person = _peopleRepository.GetPerson();
var address = _peopleRepository.GetAddress();
model.PersonModel.DateOfBirth = person.DateOfBirth;
model.PersonModel.Forename = person.Forename;
model.PersonModel.Surname = person.Surname;
model.PersonModel.Title = person.Title;
model.AddressModel.AddressLine1 = address.AddressLine1;
model.AddressModel.AddressLine2 = address.AddressLine2;
model.AddressModel.City = address.City;
model.AddressModel.County = address.County;
model.AddressModel.Postcode = address.Postcode;
model.AddressModel.Telephone = address.Telephone;
model.DocumentModel.EntityType = 1;
model.DocumentModel.ID = Globals.UserID;
model.DocumentModel.NewFile = true;
var countries = _countryRepository.GetCountries();
model.AddressModel.Countries = countries.ToSelectListItem(1, c => c.ID, c => c.CountryName, c => c.CountryName, c => c.ID.ToString());
return View(model);
}
我想测试Details方法并具有以下查询:
1)Globals.UserID属性从会话对象中检索当前用户。我如何轻松地对此进行测试(我正在使用内置的VS2010单元测试和Moq)
2)我在这里调用AttachmentHelper.GetIconFromFileName(),它只是查看文件的扩展名并显示一个图标。我还将在附件存储库中调用GetPersonAttachments,调用GetPerson,GetAddress和GetCountries,以及调用所创建的扩展方法,以将List转换为SelectListItem的IEnumerable。
该控制器动作是不良做法的一个例子吗?它使用了大量的存储库以及其他辅助方法。据我所知,对单个动作进行单元测试将需要大量的代码。这适得其反吗?
在测试项目中对一个简单的控制器进行单元测试是一回事,但是当您进入这样的现实生活中的代码时,它可能会变成怪物。
我想我的问题确实是我应该重构代码以使其更易于测试,还是为了满足当前代码而使测试变得更加复杂?
参考方案
复杂的测试与复杂的代码一样糟糕:它们很容易出现错误。因此,为了使测试简单,通常最好重构应用程序代码以使其易于测试。例如,您应该将映射代码从Details()方法中拉出到单独的帮助器方法中。然后,您可以非常轻松地测试这些方法,而不必担心测试Details()的所有疯狂组合。
我已经拉出下面的人员和地址映射部分,但是您可以将其拉得更大一些。我只是想让您了解我的意思。
public ActionResult Details() {
UserDetailsModel model = new UserDetailsModel();
foreach( var doc in _attachmentRepository.GetPersonAttachments( Globals.UserID ) ) {
DocumentItemModel item = new DocumentItemModel();
item.AttachmentID = doc.ID;
item.DocumentIcon = AttachmentHelper.GetIconFromFileName( doc.StoragePath );
item.DocumentName = doc.DocumentName;
item.UploadedBy = string.Format( "{0} {1}", doc.Forename, doc.Surname );
item.Version = doc.VersionID;
model.Documents.Add( item );
}
var person = _peopleRepository.GetPerson();
var address = _peopleRepository.GetAddress();
MapPersonToModel( model, person );
MapAddressToModel( model, address );
model.DocumentModel.EntityType = 1;
model.DocumentModel.ID = Globals.UserID;
model.DocumentModel.NewFile = true;
var countries = _countryRepository.GetCountries();
model.AddressModel.Countries = countries.ToSelectListItem( 1, c => c.ID, c => c.CountryName, c => c.CountryName, c => c.ID.ToString() );
return View( model );
}
public void MapAddressToModel( UserDetailsModel model, Address address ) {
model.AddressModel.AddressLine1 = address.AddressLine1;
model.AddressModel.AddressLine2 = address.AddressLine2;
model.AddressModel.City = address.City;
model.AddressModel.County = address.County;
model.AddressModel.Postcode = address.Postcode;
model.AddressModel.Telephone = address.Telephone;
}
public void MapPersonToModel( UserDetailsModel model, Person person ) {
model.PersonModel.DateOfBirth = person.DateOfBirth;
model.PersonModel.Forename = person.Forename;
model.PersonModel.Surname = person.Surname;
model.PersonModel.Title = person.Title;
}
ddl在服务器中未更新-asp.net - javascript我在ASP.NET c#上工作。我有一个DropDownList。 (runat =“ server”)在$ {document).ready上,我更新了它的值:$(document).ready(function () { document.getElementById("ddl").value = "abc"; ……
在ASP.NET MVC中创建数据库回调的最有效方法 - c#我有一个ASP.NET MVC网页,该网页基本上通过日期过滤器显示MS SQL数据库中表的行。当新行插入数据库表时,我想用新行列表更新网页视图。实现此目标的最有效方法是什么?基本上,我想从我的JavaScript创建一个到数据库服务器的回调,以用新结果更新UI。假设数据库表中的行数很大。(〜1百万)谢谢,cas 参考方案 如果数据库更新非常频繁,则可以按特定…
如何使用JavaScript访问嵌入式ASP.NET GlobalResources? - javascript我正在开发一个遗留的ASP.NET项目,该项目正试图缓慢地进行调整,但是如果没有像巧克力手指屋一样塌陷的情况,我将无法进行重大更改。我试图为此找到解决方案,但由于术语的特定混合(“ javascript”,“ embedded”和/或“ resource”只是为我提供了有关如何嵌入.js文件的信息,而失败了)。 。),这可能是一种怪异的处理方式。该项目将Ap…
如何使用ASP.NET ViewState使用JavaScript - c#我的页面中有UL,它为空。我开始使用JavaScript使用LI填充它。在回发阶段如何在asp.net中使用此新添加的动态数据?那是因为我的提交按钮是asp.net控件。我不想使用JS POST。谢谢 参考方案 我过去通过在隐藏字段中填充要发布的动态数据来完成此类操作,您可以-在回传之前触发JavaScript事件,该事件将数据从UL解析到隐藏字段中要么更新…
如何从.Net DLL获取公共出口列表? - c#我可以使用“ dumpbin”和“ dll export”之类的工具来查看标准win32 DLL的公共入口点(“ exports”),例如Windows \ SYSTEM32 \ GDI32.dll。但是,当我在.Net DLL上使用这些相同的工具时,我看到的仅仅是 2000 .reloc 2000 .rsrc 48000 .text 我有一个C#/。Net…