0

我想爲我的ApiController編寫一些單元測試並遇到一些問題。如何在Web API中模擬Request.form

這裏是我的TestMethod的

 [TestMethod] 
     public void CustomerController_AddUnitTest() 
     { 


      var custid = Guid.NewGuid(); 
      var customers = new Customer() { CustomerName = "Enterprise", CustomerId = custid }; 
      var rmContext = MockRepository.GenerateMock<HttpContextBase>(); 
      var rmRequest = MockRepository.GenerateMock<HttpRequestBase>(); 
      rmContext.Stub(x => x.Request).Return(rmRequest); 
      var FormData = new NameValueCollection { { "FirstName", "Jonathan" }, { "LastName", "Danylko" } }; 
      rmRequest.Stub(r => r.Form).Return(FormData); 
      rmContext.Stub(p => p.Request).Return(rmRequest); 
      var forms = rmContext.Request.Form; 

> // here i am able to get forms value but i couldn't pass these value 
> to main controller 

      var mockRepository = MockRepository.GenerateMock<ICustomerService>(); 
      mockRepository.Stub(x => x.Add(new Customer())).IgnoreArguments().Return(1); 
      _customerController = new CustomerController(mockRepository); 
      var result = _customerController.CustomerAdd(); 
      Assert.IsNotNull(result); 
     } 

這是我的控制器代碼看起來像

public int CustomerAdd() 
    { 
     var localhost = HttpContext.Current.Request.Url.Authority; 
     var formData = HttpContext.Current.Request.Form["FormData"]; 
     JavaScriptSerializer json_serializer = new JavaScriptSerializer(); 
     var customer = json_serializer.Deserialize<Customer>(formData); 
     if (HttpContext.Current.Request.Files.Count > 0) 
     { 
      HttpPostedFile file = HttpContext.Current.Request.Files[0]; 
      string fileName = customer.CustomerName.Trim() + "_" + file.FileName; 
      var filePath = HttpContext.Current.Server.MapPath(Constants.FileUploadImagePath + fileName); 
      file.SaveAs(filePath); 
      customer.Logo = fileName; 
     } 
     return _iCustomerService.Add(customer); 
    } 

我想模擬數據傳遞給var formData = HttpContext.Current.Request.Form["FormData"];

任何人都可以有一個想法來解決這個問題我真的厭倦了這個任務。

+0

被測方法設計不佳,與靜態依賴性緊密相關,這使得測試變得困難。儘量避免將你的代碼緊密耦合到'HttpContext'。 – Nkosi

+0

是的,我知道。但我不知道如何模擬這一行代碼 –

+0

var formData = HttpContext.Current.Request.Form [「FormData」]; –

回答

0

將線拉出到一個單獨的(虛擬)方法中,然後在測試中,使用控制器的部分模擬器,在該模擬器中存入新方法以返回模擬數據。 (這被稱爲「測試縫」FYI)。

事情是這樣的:

public int CustomerAdd() 
{ 
    var localhost = HttpContext.Current.Request.Url.Authority; 
    var formData = GetFormData()["FormData"]; 
    JavaScriptSerializer json_serializer = new JavaScriptSerializer(); 
    var customer = json_serializer.Deserialize<Customer>(formData); 
    if (HttpContext.Current.Request.Files.Count > 0) 
    { 
     HttpPostedFile file = HttpContext.Current.Request.Files[0]; 
     string fileName = customer.CustomerName.Trim() + "_" + file.FileName; 
     var filePath = HttpContext.Current.Server.MapPath(Constants.FileUploadImagePath + fileName); 
     file.SaveAs(filePath); 
     customer.Logo = fileName; 
    } 
    return _iCustomerService.Add(customer); 
} 

public virtual NameValueCollection GetFormDatat() 
{ 
    return HttpContext.Current.Request.Form; 
} 

然後在您的測試使用:

_customerController = MockRepository.GeneratePartialMock<CustomerContoller>(); 
_customerController.Stub(c => c.GetFormData()).Return(yourFakeFormData); 

或者,你可以做同樣的事情,但對於上下文對象的用法。

+0

作爲一般說明,您絕不希望生產代碼直接引用您的模擬框架類型。在原始文章中,您將顯示控制器類將模擬存儲庫作爲構造參數 - 這絕不應該發生。模擬框架旨在模擬您實際使用的類型,因此您的產品無需瞭解您的測試代碼。 –