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

作为一般说明,您绝不希望生产代码直接引用您的模拟框架类型。在原始文章中,您将显示控制器类将模拟存储库作为构造参数 - 这绝不应该发生。模拟框架旨在模拟您实际使用的类型,因此您的产品无需了解您的测试代码。 –