2010-08-15 35 views
9

我需要僞造HttpContext.Current.Application表才能從我的單元測試中訪問它。如何僞裝HttpContext進行單元測試?

我需要將我的數據存儲在某個地方。我認爲我可以通過NameValueCollectionBase的實例,但是因爲我發現這個基類型沒有索引器,所以它看起來太複雜了。

那麼僞造HttpContext這部分怎麼樣?可能嗎?我怎麼做到的?將NUnit.Mocks有幫助嗎?

在此先感謝...

回答

1

如果你需要的NameValueCollection基指數,請使用以下代碼

public static IEnumerable<KeyValuePair<string, string>> ToPairs(this NameValueCollection collection) 
{ 
    if(collection == null) 
    { 
     throw new ArgumentNullException("collection"); 
    } 

    return collection.Cast<string>().Select(key => new KeyValuePair<string, string>(key, collection[key])); 
} 

對於剛剛來存儲數據,並通過各地的測試方法,請使用上面的代碼。

2
+0

問題是,如果是關於'User'的話,那麼很容易返回類型爲'IPrincipal'的新對象,但是當涉及到Application時,我需要返回一些沒有公共構造函數的HttpApplicationState對象並且因爲它是通過索引器使用的,所以很難用'NUnit.Mocks'僞造......你能提供一些這種情況的代碼示例嗎? – 2010-08-15 16:44:40

+0

你好, 如果你需要的NameValueCollection基指數,請使用以下代碼 公共靜態的IEnumerable > ToPairs(這NameValueCollection中集) { 如果(集合== NULL){ 扔 新ArgumentNullException( 「集合」); } return collection.Cast ().Select(key => new KeyValuePair (key,collection [key])); } 僅用於存儲數據並傳遞測試方法,請使用上述代碼。 – Venkat 2010-08-16 12:55:17

+2

第一個鏈接不起作用 – 2012-02-01 15:01:45

0

在這種情況下,我生成了一些從System.Web.Abstractions中的基類派生的存根。我經常使用這種技術的MVC應用程序的MVC /的WebAPI控制器包含一個抽象的HttpContext(HttpContextBase)

這樣我可以存根出在我單位/集成測試HttpContext的要求,這裏是一個示例...

public class MockHttpApplicationState : HttpApplicationStateBase 
{ 
    private IDictionary<string, object> _appState = new Dictionary<string, object>(); 

    public override void Add(string name, object value) 
    { 
     _appState.Add(name, value); 
    } 

    public override object Get(string name) 
    { 
     return _appState[name]; 
    } 

    public override object this[string name] 
    { 
     get 
     { 
      return _appState[name]; 
     } 

     set 
     { 
      _appState[name] = value; 
     } 
    } 
} 

public class MockHttpContext : HttpContextBase 
{ 
    private IDictionary<string, object> _appKeys; 

    public MockHttpContext() 
    { 

    } 

    /// <summary> 
    /// Accepts a dictionary of app keys to supply to the HttpApplicationState instance 
    /// </summary> 
    /// <param name="applicationState"></param> 
    public MockHttpContext(IDictionary<string,object> applicationState) 
    { 
     _appKeys = applicationState; 
    } 

    public override Cache Cache 
    { 
     get 
     {     
      return HttpRuntime.Cache; 
     } 
    } 

    public override HttpApplicationStateBase Application 
    { 
     get 
     { 
      var mockAppState = new MockHttpApplicationState(); 

      foreach (string key in _appKeys.Keys) 
      { 
       mockAppState.Add(key, _appKeys[key]); 
      } 

      return mockAppState; 
     } 
    } 

    public override HttpRequestBase Request 
    { 
     get 
     { 
      return new HttpRequestWrapper(new HttpRequest(null,"http://localhost",null)); 
     } 
    } 
} 

然後我的測試可以建立控制器和HTTP上下文:

private readonly OnlineShop.MVC.Controllers.HomeController _controller = 
     new MVC.Controllers.HomeController(null,new UnitOfWork()); 

    [OneTimeSetUp] 
    public void Init() 
    { 
     var appKeys = new Dictionary<string, object>(); 

     appKeys.Add("localhost", 1); 

     var httpContext = new MockHttpContext(appKeys); 

     _controller.ControllerContext = new ControllerContext() 
     { 
      Controller = _controller, 
      RequestContext = new RequestContext(httpContext, new RouteData())  
     };       
    } 

    [Test] 
    public void Index_Returns_HomeView() 
    {    
     var view = _controller.Index() as ViewResult; 
     var viewModel = view.Model as MVC.ViewModels.Home; 

     Assert.IsInstanceOf<OnlineShop.MVC.ViewModels.Home>(viewModel); 
     Assert.IsTrue(viewModel.FeaturedProducts.Count > 0); 
    } 

我的控制器是意識到它的環境HttpContextBase實例提供緩存和應用程序狀態:

public ActionResult Index() 
    {       
     string cacheKey = string.Format("FeaturedProducts-{0}",WebsiteId); 
     IList<Product> productList = this.HttpContext.Cache[cacheKey] as IList<Product>; 


     //My app keeps a list of website contexts in the Application. This test returns 1 based on the unit/int tests or a real world db value when hosted on IIS etc.. 
     int websiteId = (int)HttpContext.Application[this.Request.Url.Host];