我正在尝试将单元测试添加到现有的代码库中,由于网站的构建方式,我几乎陷入了第一道障碍。
为了详细说明,本站点中的每个控制器都继承自一个名为SiteController的基本控制器,该控制器的构造函数使用静态助手类填充一些数据。
例如
public class HomeController : SiteController
{
public ActionResult Index()
{
//Do stuff here
}
}
这是基本控制器
public class SiteController
{
public SiteController()
{
viewModel = CategoryHelper.GetAllCategories();
}
}
静态GetAllCategories帮助方法
public static class CategoryHelper
{
public static IList<string> GetAllCategories()
{
//Go off and get the categories from the WCF layer
return _categories;
}
}
我无法模拟静态类,但是如何重构此代码以便我可以使用单元测试来处理它。我们已经在整个站点中使用了DI,我知道这里的理论 - 我应该将这个静态类包装在一个抽象层中,这对于一般的代码来说更好。但这种实用性我不太确定。
这可能是显而易见的,但我的目标是保持网站工作(显然),但也要重写静态类或调用它,以便我可以对它进行单元测试。我刚开始编写单元测试,所以我只是遇到了这些问题,然后才能看到一个绿色标记通过测试!当我知道理论解决方案但却不知道该怎么做才能让它发挥作用时,这是令人沮丧的,而且是双倍的。
答案 0 :(得分:2)
public class HomeController : SiteController
{
public HomeController(ICategoryHelper categoryHelper) : base(categoryHelper)
{
}
public ActionResult Index()
{
//Do stuff here
}
}
public class SiteController
{
public SiteController(ICategoryHelper categoryHelper)
{
viewModel = categoryHelper.GetAllCategories();
}
}
public class CategoryHelper : ICategoryHelper
{
public IList<string> GetAllCategories()
{
//Go off and get the categories from the WCF layer
return _categories;
}
}
public interface ICategoryHelper
{
IList<string> GetAllCategories();
}
最重要的是对抽象进行编码,而不是具体的类。 CategoryHelper是一个具体的类,你希望你的控制器利用执行工作的东西而不关心它是如何完成的。因此,您的控制器应该在其构造函数中接受一个接口(如果需要,可以将其传递给基本控制器)。
同样,CategoryHelper应该实现一个接口,这基本上是一个合同说&#34;我可以执行ICategoryHelper的工作&#34;。
然后,连接CategoryHelper以满足与依赖项注入器的ICategoryHelper依赖关系。如何执行此操作取决于您使用的特定工具(AutoFac,Ninject,SimpleInjector等)。
注意:如果类别不经常更改,则缓存模式可能会更好。