【问题标题】:C# Unit Testing: Testing a method that uses MapPathC# 单元测试:测试使用 MapPath 的方法
【发布时间】:2009-08-11 17:07:36
【问题描述】:

首先,我知道这个问题非常接近: How to MapPath in a unit test in C#

不过,我希望它有不同的解决方案。我的问题如下:

在我的代码中,我有一个需要验证的对象。我正在为每种验证方法创建单元测试,以确保它正确验证。我正在创建模拟数据并将其加载到对象中,然后对其进行验证。问题是在验证中,当发生错误时,会分配一个错误代码。此错误代码用于使用 Server.MapPath 从 xml 文件中收集有关错误的信息。但是,在尝试获取 xml 文件时,会抛出异常,意味着找不到该文件。

由于 MapPath 在我的验证代码中,而不是在我的单元测试中,我如何让我的单元测试识别路径?这个问题有意义吗?

错误行(在我的验证代码中不是我的单元测试):

XDocument xdoc = XDocument.Load(HttpContext.Current.Server.MapPath("App_Data/ErrorCodes.xml"));

简化:单元测试在我的程序中调用一个方法,该方法调用 Server.MapPath,然后失败。

【问题讨论】:

    标签: c# .net unit-testing server.mappath


    【解决方案1】:

    我会将“文件名提供程序”抽象为一个只返回位置的类,然后您可以轻松得多地模拟它。

    public class PathProvider
    {
        public virtual string GetPath()
        {
            return HttpContext.Current.Server.MapPath("App_Data/ErrorCodes.xml");
        }
    }
    

    然后,您可以直接使用 PathProvider 类...

    PathProvider pathProvider = new PathProvider();
    XDocument xdoc = XDocument.Load(pathProvider.GetPath());
    

    或者在你的测试中模拟它:

    PathProvider pathProvider = new MockPathProvider(); // using a mocking framework
    XDocument xdoc = XDocument.Load(pathProvider.GetPath());
    

    【讨论】:

    • GetPath() 应该是虚拟的。
    • @Dan HttpContext.Current。当我们从 TestProject 运行时返回 null。有什么办法可以避免这种情况?
    • @JibinMathew 是的,不要使用HttpContext.Current。我知道这听起来很滑稽,但这是真的。一般来说,不要模拟你不拥有的类,但你可以为 HttpContextBase 编写一个包装类,它实现了你想要的功能。
    • @DanAtkinson 如何
    • @Sana 我不知道这是否是一个问题。如果是,请检查它是否已被回答,如果没有,则将其作为问题而不是评论提出。
    【解决方案2】:

    经过严格的谷歌搜索和同事的帮助,我们想出了一个已经内置到 .net 中的简单解决方案

    在访问验证过程的单元测试之上,我补充说:

     [TestMethod()]
     [HostType("ASP.NET")]
     [UrlToTest("http://localhost:###/upload_file.aspx")]
     [AspNetDevelopmentServerHost("Path To Web Application", "Path To Web Root")]
    

    这非常有效。基本上,当调用测试时,它会在页面加载中加载带有指定单元测试的 URL。由于它是一个正在调用单元测试的网站,因此验证将可以访问 Server.MapPath。这个解决方案可能并不适合所有人,但它非常适合这个。感谢您所做的一切。

    【讨论】:

    • 像这样的集成测试对于确保所有部分协同工作肯定很有用,但还有其他情况(如丢失的文件),此解决方案无法处理。生成测试 Web 应用程序也是一项相当昂贵的操作,如果您经常运行测试,它可能会增加。
    • 同意,虽然这个解决方案在运行时可以提供有用的信息方面有一些优点,但它不是任何意义上的单元测试,它缺乏实际单元测试的大部分好处。
    • 这样可以节省大量时间!!
    【解决方案3】:

    尝试使用 Rhino Mocks 或其他模拟框架来模拟 httpContext(或其他依赖对象) 或者您可以编写自己的模拟对象。 或者编写一个 MapPathWrapper 类,从一个 MapPathWrapperBase 类继承你的真实环境,然后在你的单元测试中创建一个 MockMapPathWrapper 对象。

    应该有很多模拟 SO 的例子。

    这是我问的一个:

    How to use Rhino Mocks to Mock an HttpContext.Application

    更新 我只有使用 Asp.Net MVC 的经验,使用我想象的 webforms 会更困难,因为缺少 HttpContextBase 类。

    【讨论】:

      【解决方案4】:

      我会提取接受你的依赖作为参数的方法:

      public void Validate(HttpContext context)
      {
          ValidatePath(context.Server.MapPath("App_Data/ErrorCodes.xml"));
      }
      
      public void ValidatePath(string path)
      {
          XDocument xdoc = XDocument.Load(path);
          ValidateDocument(xdoc);
      }
      
      public void ValidateDocument(XDocument xdoc)
      {
          // Original code
      }
      

      然后您可以独立测试各种方法。例如,测试ValidatePath() 如何处理丢失的文件。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-11-08
        • 1970-01-01
        • 1970-01-01
        • 2013-06-30
        • 1970-01-01
        • 1970-01-01
        • 2020-08-29
        • 2012-11-05
        相关资源
        最近更新 更多