2014-01-06 25 views
0

我必須單元測試ASP.NET MVC 4.0中非常大且未格式化的方法之一。如何在mvc中對未格式化的方法進行單元測試?

下面是操作方法的代碼: -

public ActionResult GetDetails(string ProdName, int ProdArea, int ProdAreaId= 0) 
    { 
     if (ProdAreaId == 0 && ProdArea == 1 && System.Web.HttpContext.Current.Session["ResponseProdAreaId"] != null) 
     { 
      ProdAreaId = (int)System.Web.HttpContext.Current.Session["ResponseProdAreaId"]; 
     } 
     if (string.IsNullOrEmpty(ProdName)) 
     { 
      if (System.Web.HttpContext.Current.Session["ProdName"] == null) 
      { 
       ProdName = Guid.NewGuid().ToString(); 
       System.Web.HttpContext.Current.Session["ProdName"] = ProdName; 
      } 
      else 
      { 
       ProdName = System.Web.HttpContext.Current.Session["ProdName"].ToString(); 
      } 
     } 
     else 
     { 
      ProdName = ProdName.Replace("___", " "); 
     } 


     List<StateDetail> stateList = ProductService.GetAllStates().Where(n => n.FKCountryID == (int)Countries.UnitedStates).ToList(); 

     ProductAddressViewModel model = new ProductAddressViewModel 
     { 
      ProdArea = ProdArea, 
      FKProductID = CurrentProductId 
     }; 

     model.States = stateList != null ? new SelectList(stateList, "StateID", "StateCode") : null; 

     if (System.Web.HttpContext.Current.Session[「ProdAddresses」] != null && ProdAreaId == 0 && ProdArea == 1) 
     { 
      List<ProductAddressDto> lstprodaddresses = (List<ProductAddressDto>)System.Web.HttpContext.Current.Session[「ProdAddresses」]; 
      if (lstprodaddresses.Count > 0) 
      { 
       AddressDto addrDto = lstprodaddresses.First().Address; 
       //save address in DB 
       model.Address1 = addrDto.Address1; 
       model.Address2 = addrDto.Address2; 
       model.ProdArea = 1; 
       model.City = addrDto.City; 
       model.IsDefault = true; 
       model.ProdName = model.ProdName; 
       model.SelectedAddressTypeID = (int)AddressType.Street; 
       model.ZIPCode = addrDto.ZIPCode; 
       model.SelectedStateId = addrDto.FKStateID; 
       model.AddressTypes = GetAddressTypes(); 
      } 
     } 
     else if (model.FKProductID > 0) 
     { 
      ToolDto tool = ToolService.GetToolDetails(model.FKProductID); 

      if (ProdAreaId > 0) 
      { 
       model.AddressTypes = GetAddressTypes(); 
       ProductAddressDto prodaddr = tool.ToolAddresses.First(n => n.Tool_AddressID == ProdAreaId); 
       model.Address1 = prodaddr.Address.Address1; 
       model.Address2 = prodaddr.Address.Address2; 
       model.City = prodaddr.Address.City; 
       model.SelectedStateId = prodaddr.Address.FKStateID; 
       model.ZIPCode = prodaddr.Address.ZIPCode; 
       model.SelectedAddressTypeID = prodaddr.Address.FKAddressTypeID; 
       model.IsDefault = prodaddr.IsDefault; 
       model.FKAddressID = prodaddr.FKAddressID; 
       model.Tool_AddressID = prodaddr.Tool_AddressID; 
       model.FKProductID = prodaddr.FKProductID; 
       model.AddressTypes = GetAddressTypes(); 
      } 
      else 
      { 
       //address types 
       List<int> excludeAddrTypes = new List<int>(); 
       foreach (ProductAddressDto prodadrdto in tool.ToolAddresses) 
       { 
        if (prodadrdto.Tool_AddressID != ProdAreaId) 
        { 
         excludeAddrTypes.Add(prodadrdto.Address.FKAddressTypeID); 
        } 
       } 
       if (System.Web.HttpContext.Current.Session[「ProdAddresses」] != null) 
       { 
        excludeAddrTypes.Add((int)AddressType.Street); 
       } 

       var addrtypes = from AddressType e in Enum.GetValues(typeof(AddressType)) 
           where !excludeAddrTypes.Contains((int)e) 
           select new { Id = (int)e, Name = e.ToString() }; 

       model.AddressTypes = addrtypes.Select(x => new SelectListItem 
       { 
        Value = x.Id.ToString(), 
        Text = x.Name 
       }); 
       if (tool.ToolAddresses.Count == 0) 
       { 
        model.IsDefault = (ProdArea == 1); 
       } 
      } 
     } 
     else 
     { 
      //filter out address types if responsed tool is there 
      if (System.Web.HttpContext.Current.Session[「ProdAddresses」] != null) 
      { 
       List<int> excludeAddrTypes = new List<int>(); 
       excludeAddrTypes.Add((int)AddressType.Street); 
       var addrtypes = from AddressType e in Enum.GetValues(typeof(AddressType)) 
           where !excludeAddrTypes.Contains((int)e) 
           select new { Id = (int)e, Name = e.ToString() }; 
       model.AddressTypes = addrtypes.Select(x => new SelectListItem 
       { 
        Value = x.Id.ToString(), 
        Text = x.Name 
       }); 
      } 
      else 
      { 
       model.AddressTypes = GetAddressTypes(); 
      } 
      model.IsDefault = (ProdArea == 1); 
     } 
     model.ProdName = ProdName; 
     return PartialView("_AddUpdateAddress", model); 
    } 

可能是方法不正確format.But我必須這樣做的單位testing.I有做,在幾個不同的但我不確定它的正確性。 我想知道,我們應該如何對這樣一個大而無格式的方法進行單元測試。

任何人都可以幫我解決這個問題嗎?

下面是一張我的單元測試方法的代碼: - 所有的

[TestMethod] 
    public void GetDetailsTest_NotEmpty() 
    {      
     var ProdName = random.ToString(); 
     var ProdArea = random.Next(); 
     var ProdAreaId = 0; 

     var _toolServiceMock = new Mock<IToolService>(); 
     var _lookupServiceMock = new Mock<ILookupService>(); 

     var stateList = new List<StateDto> { 
      new StateDto() { StateID = random.Next(), StateCode = Guid.NewGuid().ToString(), Description = random.ToString(), FKCountryID = 1 }, 
      new StateDto() { StateID = random.Next(), StateCode = Guid.NewGuid().ToString(), Description = random.ToString(), FKCountryID = random.Next() }, 
     }; 

      _lookupServiceMock.Setup(s => s.GetAllStates()).Returns(stateList); // .Returns(stateList); 

     //Arrange 
     CustomerDto cust = _toolService.LookupCustomers("", "").FirstOrDefault(); 
     if (cust != null) 
     { 
      ToolDto tool = _toolService.GetToolDetails(cust.Tool.toolId); 
      if (tool.ToolAddresses.Count > 0 && tool.ToolAddresses.First().Address != null) 
      { 
       HttpContext.Current.Session["FKToolID"] = cust.FKToolID; 

       var controller = new ToolController(_toolServiceMock.Object); 

       PartialViewResult result = controller.SelectAddress(cust.Tool.Name, 1, tool.ToolAddresses.First().Tool_AddressID) as PartialViewResult; 
       var viewmodel = (ToolAddressViewModel)((ViewResultBase)(result)).Model; 
       if (viewmodel != null) 
       { 
        //Act      
        Assert.AreEqual(tool.ToolAddresses.First().Address.Address1, viewmodel.Address1); 
        Assert.AreEqual("_AddUpdateAddress", result.ViewName); 
        Assert.IsInstanceOfType(viewmodel, typeof(ToolAddressViewModel)); 
       } 

       //Act 
       _lookupServiceMock.VerifyAll(); 
      } 
     } 
    } 
+0

首先定義您想要測試的預期行爲。 – Maess

+2

如果方法太大,測試真的很難。測試將成爲單元測試和集成測試之間的事情。而是將其重構爲可測試的。使用集成測試來確保你沒有破壞任何東西。 – Palec

+0

同意上述內容。由於你的控制器動作太多,你不能把它作爲一個單元來測試 - 再加上你的測試*實際*驗證。如果你真的想做這個測試,你需要重構並且失去對HttpContext/Session的硬性依賴。 –

回答

0

首先,你的方法是一個太複雜和太長時間。 使您的行動簡短,並有一個尊重SOLID原則的責任(http://en.wikipedia.org/wiki/SOLID_(object-oriented_design))。 它會讓你的方法更容易測試。

爲了幫助你解決問題,你可以做一些快速與您的代碼:

  • 一個關注斯普利特的內部虛擬方法,你的動作每個(內部要在你的單元測試項目可測試,虛擬到能夠嘲笑他們)。
  • 在你的控制器上放置[assembly:InternalsVisibleTo(「YourTestAssembly」)]
  • 在你的單元測試項目中,你將能夠單獨測試你的任何內部方法。
  • 最後,測試你的行動,用嘲弄的框架(RhinoMock,MOQ)嘲笑你所有的內部虛擬方法和測試行動的邏輯(用嘲諷的框架生成的代理可以讓你模擬虛擬方法)。

這是在不破壞現有應用的情況下測試邏輯的最簡單方法。 不方便的是,你的邏輯是內部方法,讓整個組件能夠使用它。

相關問題