【问题标题】:Mocking HttpContext.server.MapPath in ASP.NET unit testing在 ASP.NET 单元测试中模拟 HttpContext.server.MapPath
【发布时间】:2015-05-10 14:38:04
【问题描述】:

我在 ASP.Net Web 应用程序中进行单元测试,现在我可以访问模型文件中的构造函数来测试哪个具有用于上传我的 XML 文件的 Server.MapPath 代码,当尝试测试这个时我得到错误,因为HttpContext 为空,所以我必须模拟 Server.MapPath。

我已经搜索了很多,但每个示例仅针对 Asp.NET MVC,但我在 ASP.NET 中工作。所以请帮助 ASP.NET 解决这个问题。

我的代码如下。

public class NugetPlatformModel
{
    public bool IsHavingLicense { get; set; }
    public List<PlatformProducts> PlatformProduct = new List<PlatformProducts>();
    public NugetPlatformModel()
    {
      var xmldoc = new XmlDocument();

       mldoc.Load(HttpContext.Current.Server.MapPath(@"~\Content\PlatformProducts.xml"));
    }
}

还有我的单元测试代码

 [Test]
    public void Account_UnlicensedCustomerIdentity_IsStudioLicenseAndIshavinglicenseFalse()
    {

        //Act
        NugetPlatformModel nugetPlatformModel = new NugetPlatformModel();

        //Assert
        AssertEquals(false, nugetPlatformModel.IsHavingLicense);

    }

【问题讨论】:

    标签: c# asp.net asp.net-mvc unit-testing


    【解决方案1】:

    这在调用静态方法的代码中很常见,在保持关注点分离和避免紧密耦合的同时很难进行测试。这是测试和模拟“不可测试代码”的通用方法:为其编写“外观包装器”。

    • 为这些方法创建一个包装器。一个简单的类,其中包含合理命名的方法,并且只委托给不可测试的调用(通常是静态调用)

    • 为该包装类创建一个接口

    • 不要在客户端代码中直接调用不可测试的方法,而是使用包装器(使用步骤 2 中提供的接口注入依赖项)并在其上调用普通方法。

    • 在您的单元测试中,使用您想要的行为模拟包装器。

    这种方法有效地减少了耦合,分离了需要分离的关注点。当然,您仍然无法测试包装器本身的行为,但如果它足够简单(仅委托给原始调用),那么问题不大。

    更新:

    Using shims to isolate your application from other assemblies for unit testing

    Shim 类型是 Microsoft Fakes Framework 用来让您轻松地将被测组件与环境隔离的两种技术之一。 Shims 将调用转移到您在测试中编写的特定方法的代码。许多方法会根据外部条件返回不同的结果,但 shim 受您的测试控制,并且可以在每次调用时返回一致的结果。这使您的测试更容易编写。 使用 shim 将您的代码与不属于您的解决方案的程序集隔离开来。要将解决方案的组件相互隔离,我们建议您使用存根。

    【讨论】:

    • 谢谢JJJ。我无法编辑我的源代码还有其他方法吗?
    • 另一种方法是将HttpContext.Current.Server.MapPath(@"~\Content\PlatformProducts.xml")替换为Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Content\PlatformProducts.xml")
    • 更新了我的答案。参考那个。
    • 根据msdn.microsoft.com/en-us/library/hh549175.aspx(适用于 Visual Studio 2015),Fakes Framework 需要 Visual Studio Enterprise
    【解决方案2】:

    已经回答了,你应该解耦你的系统

    public class NugetPlatformModel
      {
        public bool IsHavingLicense { get; set; }
        public List<PlatformProducts> PlatformProduct = new List<PlatformProducts>();
        public NugetPlatformModel(IPlatformProductProvider provider)
        {
          var xmldoc = new XmlDocument();
          //System.Web.HttpContext.Current.Server.MapPath(@"~\Content\PlatformProducts.xml")
          xmldoc.Load(provider.Filepath);
        }
    
        public interface IPlatformProductProvider
        {
          string Filepath { get; }
        }
    
        public class PlatformProductProvider: IPlatformProductProvider
        {
          string _filepath;
          public string Filepath
          {
            get { return _filepath; }
            set { _filepath = value;}
          }
    
          public PlatformProductProvider(string path)
          {
            _filepath = path;
          }
        }
    
      }
    

    你的测试可能是:

    [Test]
        public void Account_UnlicensedCustomerIdentity_IsStudioLicenseAndIshavinglicenseFalse()
        {
          //Arrange
          // using Moq
          //var mock = new Mock<IPlatformProductProvider>();
          //IPlatformProductProvider provider = mock.Object;
          //provider.Filepath = "pippo.xml";
          // otherwise
                var provider = new PlatformProductProvider("pippo.xml");
    
          //Act
          NugetPlatformModel nugetPlatformModel = new NugetPlatformModel(provider);
    
          //Assert
          AssertEquals(false, nugetPlatformModel.IsHavingLicense);
    
        }
    

    【讨论】:

      【解决方案3】:

      如果无法修改源代码,请尝试使用 shims (https://msdn.microsoft.com/en-us/library/hh549176.aspx)。

      【讨论】:

        猜你喜欢
        • 2019-12-13
        • 1970-01-01
        • 1970-01-01
        • 2016-11-22
        • 2014-01-14
        • 2017-02-09
        • 2018-11-27
        • 1970-01-01
        • 2015-05-04
        相关资源
        最近更新 更多