如何在UnitTest asp.net中使用应用程序变量

时间:2015-03-02 16:04:05

标签: c# asp.net unit-testing

我有一个方法,它使用Application变量从外部文件中获取信息。由于Application变量不用于单元测试,有没有办法从Global.asax文件中获取Application变量值并能够在测试中使用它们?

这是我的测试方法:

[TestMethod]
public void TestGetCompanyList()
{
    var accController = new AccSerController();
    CInt cInt = new CInt();
    cIn.Iss = "Other";
    cIn.Tick = "BK";
    var result
      = accController.Clist(cIn) as IEnumerable<CList>;
    Assert.IsNotNull(result);
}

3 个答案:

答案 0 :(得分:2)

使用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配置中,您告诉它在需要WebConfiguration时使用ISiteConfiguration。所以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实现。

答案 1 :(得分:0)

我在一些测试中完成了以下操作。不理想,但它完成了工作。

if (System.Web.HttpContext.Current != null)
{
     //   Fill your application variable
}
else
{
     //   Get your data from somewhere else                    
}

答案 2 :(得分:0)

据我所知,有两种方法可以对这种情况进行单元测试。

第一个是基于将控制器功能分成两个:一个是控制器功能本身,另一个是实现逻辑(例如:这是你测试的那个)。例如:

在:

public void MyControllerFunction()
{
    var x = Context["variable"];
    do-something-with-x;
}

后:

public void MyControllerFunction()
{
    var x = Context["variable"];
    MyControllerLogic(x);
}

internal void MyControllerLogic(object x)
{
    do-something-with-x;
}

然后在单元测试中测试MyControllerLogic()函数而不是MyControllerFunction()

另一种方法是在调用单元测试之前创建一个代理上下文。

示例:

var controller = new MyController();
controller.Request = new HttpRequestMessage();
controller.Configuration = new HttpConfiguration();
controller.Request.Content = new StringContent("{ x: 21 }",
     Encoding.Unicode);
controller.Request.Content.Headers.ContentType.MediaType =
     "application/json";

请注意,我没有在第二个例子中创建HttpContext,我不确定是否需要它。您可能应该能够以与您使用的其他变量类似的方式创建它。无论如何,它都是一种黑客攻击,所以请将其视为