使用repository pattern。你的控制器不应该知道WebConfiguration。
//This defines the stuff that your controller needs (that your repository should contain)
public interface ISiteConfiguration
{
string Setting1 {get; set;}
}
//Use this in your site. Pull configuration from external file
public class WebConfiguration : ISiteConfiguration
{
public string Setting1 {get; set;}
public WebConfiguration()
{
//Read info from external file here and store in Setting1
Setting1 = File.ReadAllText(HttpContext.Current.Server.MapPath("~/config.txt"));
}
}
//Use this in your unit tests. Manually specify Setting1 as part of "Arrange" step in unit test. You can then use this to test the controller.
public class TestConfiguration : ISiteConfiguration
{
public string Setting1 {get; set;}
}
我正在使用Ninject 执行依赖注入,但还有很多其他库。我将从我的答案中省略一些基本的 Ninject 设置,因为那里有 plenty of resources。但下面的代码显示了如何在 Web 应用程序中指定使用 WebConfiguration 来满足 ISiteConfiguration 的需求。
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ISiteConfiguration>().To<WebConfiguration>();
}
这就是魔法发生的地方。当您的控制器实例在您的 Web 应用程序中创建时,Ninject 将查看构造函数并看到它正在请求ISiteConfiguration。在您的 Ninject 配置中,您告诉它在需要 ISiteConfiguration 时使用 WebConfiguration。因此,Ninject 将创建一个新的 WebConfiguration 实例并将其提供(注入)给您的控制器。
public class AccountServiceController
{
ISiteConfiguration Config {get; set;}
//This is called constructor injection
public AccountServiceController(ISiteConfiguration config)
{
Config = config;
}
public ActionResult Index()
{
//Now you can use Config without needing to know about ISiteConfiguration's implementation details
//Get settings from Config instead of Application
}
}
您也可以在单元测试中使用 Ninject,但这里有一个更简单的演示,我们没有使用它:
[TestMethod]
public void TestGetCompanyList()
{
//Arrange
var config = new TestConfiguration(){ Setting1 = "mysetting" };
var accountController = new AccountServiceController(config);
}
所有这些的结果是您可以轻松地使用控制器的操作方法进行单元测试,因为您可以使用任何您想要的ISiteConfiguration 实现。