2015-03-02 18 views
2

我有一個使用應用程序變量從外部文件獲取信息的方法。由於應用程序變量不在單元測試中使用,有沒有辦法從我的Global.asax文件中獲取應用程序變量值,並且能夠在測試中使用它們?如何在UnitTest中使用應用程序變量asp.net

這是我的測試方法:

[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); 
} 
+0

請關注此問題http://stackoverflow.com/questions/12023517/unit-test-controller-that-uses-application-scoped-variables或http://haacked.com/archive/2005/06/11/simulating_httpcontext .aspx/ – HaveNoDisplayName 2015-03-02 16:06:32

+0

我看到了第一個鏈接,但並沒有真正遵循(即時消息新)。現在看第二個鏈接。 – User456789 2015-03-02 16:10:23

+0

你是如何加載應用程序變量的? – Lareau 2015-03-02 16:16:56

回答

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配置中,當它需要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的實現。

0

我已經做了我的一些測試以下。不理想,但它完成了工作。

if (System.Web.HttpContext.Current != null) 
{ 
    // Fill your application variable 
} 
else 
{ 
    // Get your data from somewhere else      
} 
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的,我不知道,如果是有要求的。你可能應該能夠以類似的方式創建它,以及你使用的其他變量。無論如何,這是一種黑客,所以把它當作

相關問題