C# 如何在C中映射单元测试中的路径#

C# 如何在C中映射单元测试中的路径#,c#,C#,我想在单元测试中加载一个外部XML文件,以测试该XML上的一些处理代码。如何获取文件的路径 通常在web应用程序中,我会: XDocument.Load(Server.MapPath("/myFile.xml")); 但很明显,在我的单元测试中,我没有对服务器或HttpContext的引用,所以我如何映射路径,从而不必指定完整路径 更新: 我只想说明,我实际测试的代码是针对XML解析器类的,比如: public static class CustomerXmlParser { public

我想在单元测试中加载一个外部XML文件,以测试该XML上的一些处理代码。如何获取文件的路径

通常在web应用程序中,我会:

XDocument.Load(Server.MapPath("/myFile.xml"));
但很明显,在我的单元测试中,我没有对服务器或HttpContext的引用,所以我如何映射路径,从而不必指定完整路径

更新:

我只想说明,我实际测试的代码是针对XML解析器类的,比如:

public static class CustomerXmlParser {
  public static Customer ParseXml(XDocument xdoc) {
    //...
  }
}

所以为了测试这一点,我需要解析一个有效的XDocument。正在测试的方法不访问文件系统本身。我可以直接从测试代码中的字符串创建XDocument,但我认为从文件加载它会更容易。

就我个人而言,我对任何依赖后端的代码都非常谨慎 资源存储,无论是文件系统还是数据库-您在单元测试中引入的依赖关系可能导致误判,即测试失败不是因为您的特定测试代码,而是因为文件不存在或服务器不可用等。
对于什么是单元测试,更重要的是什么不是单元测试,IMO对此有一个很好的定义

您的单元测试应该测试一个原子的、定义良好的功能,而不是测试一个文件是否可以加载。 一种解决方案是“模拟”文件加载—有多种方法可以实现这一点,但我个人只会模拟您正在使用的文件系统的接口,而不会尝试进行任何完整的文件系统模拟—这是一篇关于文件系统模拟的好文章,也是一篇关于文件系统模拟的好讨论


希望对您有所帮助通常对于单元测试,我会将xml文件作为嵌入式资源添加到项目中,并使用如下方法加载它们:

public static string LoadResource(string name)
{
  Type thisType = MethodBase.GetCurrentMethod().DeclaringType;
  string fullName = thisType.Namespace + "." + name + ".xml";

  using (Stream stream = thisType.Module.Assembly.GetManifestResourceStream(fullName))
  {
      if(stream==null)
      {
        throw new ArgumentException("Resource "+name+" not found.");
      }

      StreamReader sr = new StreamReader(stream);
      return sr.ReadToEnd();
  }
}

另一个想法是利用依赖注入

public interface IPathMapper {
string MapPath(string relativePath);
}
然后简单地使用2个实现

public class ServerPathMapper : IPathMapper {
     public string MapPath(string relativePath){
          return HttpContext.Current.Server.MapPath(relativePath);
     }
}
然后还需要模拟实现

public class DummyPathMapper : IPathMapper {
    public string MapPath(string relativePath){
        return "C:/Basedir/" + relativePath;
    }
}

然后,所有需要映射路径的函数只需要访问IPathMapper的实例——在web应用程序中需要是ServerPathMapper,在单元测试中需要是DummyPathMapper——基本DI(依赖项注入)编辑:我从零开始,因为我想我一开始对你的问题的理解是错误的

在单元测试中加载XML文件以便将其注入某些类的最佳方法是在MS单元测试中使用DeploymentItem属性

如下所示:

[TestMethod]
[DeploymentItem(@"DataXmlFiles\MyTestFile.xml", "DataFiles")]
public void LoadXMLFileTest()
{
   //instead of "object" use your returning type (i.e. string, XDocument or whatever)
   //LoadXmlFile could be a method in the unit test that actually loads an XML file from the File system
   object myLoadedFile = LoadXmlFile(Path.Combine(TestContext.TestDeploymentDir, "DataFiles\\MyTestFile.xml"));

   //do some unit test assertions to verify the outcome
}
我现在没有在调试器上测试代码,但它应该可以工作

编辑: 顺便说一下,当您使用DealMyTimeTm考虑这个帖子时,

类:

internal class FakeHttpContext : HttpContextBase
{
    public override HttpRequestBase Request { get { return new FakeHttpRequest(); } }
}

internal class FakeHttpRequest : HttpRequestBase
{
    public override string MapPath(string virtualPath)
    {
        return /* your mock */
    }
}
用法:

[TestMethod]
public void TestMethod()
{
    var context = new FakeHttpContext();
    string pathToFile = context.Request.MapPath("~/static/all.js");
}

这可能对某人有帮助。我有一个相关的问题。想要使用我的c#单元测试项目中根级别文件夹中的Excel文件

我有一个名为“TestFiles”的根级别文件夹。里面有“Test.xlsx”

我所做的是:

右键单击“Test.xlsx”,转到属性并设置“复制到输出目录”=“始终复制”

现在,文件及其包含文件夹“TestFiles”总是被复制到单元测试项目的bin文件夹中。所以我可以这样使用它:

var filePath = "TestFiles/Test.xlsx";
var strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath + ";Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=0\"";
using (var conn = new OleDbConnection(strConn))
{
                conn.Open();
...
}

需要明确的是,我不是在测试是否可以加载XML或测试文件的内容,而是在测试一段需要解析XDocument的代码。文件与测试一起定位如果它没有加载,那么测试将显示错误,而不是假阴性。我意识到这并不理想,但我不知道还有其他方法。我已经更新了我的问题。当然这是重点,不是吗?您的代码正在测试解析器,因此它从何处获取xml数据是无关的,并且不会因为文件不存在而失败。就我个人而言,我会选择字符串选项,或者您可以将其作为嵌入式资源使用。这里的接口有什么好处?。相反,我们可以简单地创建2个类文件并相应地调用它们吗?1个来自实际应用程序,1个来自测试端点?有人能在这里解释一下这个接口的好处吗?通过使用类,您需要决定让一个类继承另一个类,以使类型系统满意。让您的测试实现继承真实的实现,或者以另一种方式进行,这并不是一个理想的解决方案。通过这种方式,您根本不需要让您的真实实现和测试实现相互了解——它们只是需要满足一个公共接口。