在C#项目中包含用于单元测试的资源文件

时间:2010-07-20 12:02:06

标签: c# unit-testing assemblies

我有一些阅读和阅读的功能修改文件。为了使单元测试独立于任何文件系统问题,我想将文件包含在项目中。

但是,我的函数应该是获取filePath,而我从程序集中获得的只是一个FileStream。知道如何在项目中获取资源文件的文件路径吗?

System.Reflection.Assembly a = System.Reflection.Assembly.Load(assemblyName);
FileStream stream = a.GetFile(assemblyName + "." + fileName);

谢谢!

4 个答案:

答案 0 :(得分:8)

我解决这个问题的常用方法是重构我的程序,在调用方法中打开文件然后传递一个Stream,而不是传递文件名并在那里打开文件。

对于测试,这允许我传递一个MemoryStream,这样我就可以在不使用文件系统的情况下编写单元测试。有时甚至更容易检查数据是否已正确写入并且速度更快,尤其是对于更多数量的测试。您必须记住在写入后刷新MemoryStream,因为.NET并不总是自动执行此操作。

我的一个程序示例:

public TestSaveAndLoad()
{
  [... create data to save ...]
  using (MemoryStream targetStream = new MemoryStream())
  {
    target.Save(targetStream);
    targetStream.Flush();
    targetStream.Seek(0, ...);
    target.Load(targetStream);
  }
  [... assert that the loaded data equals the saved data ...]
}

答案 1 :(得分:4)

文件系统上不存在嵌入式资源,因此它没有任何文件路径。

您有两种选择:

  • 更改SUT的API,使其接受Stream而不是文件路径。此解决方案非常优选
  • 在单元测试期间将嵌入资源保存到临时文件中,确保在每个测试用例后再次删除它。

第一个解决方案是TDD如何推动我们走向更好,更灵活的API 的一个很好的例子。

答案 2 :(得分:1)

您可以在构建项目时将数据文件设置为bin目录,然后在测试中通过Directory.GetCurrentDirectory()引用它们。或者甚至将它们保留在原来的位置,只需使用基于当前目录的相对路径。

但更好的方法是重构代码以依赖Stream类,然后使用模拟和依赖注入的组合来为数据提供模拟流 - 或者如果伪造效果更好,则使用内存流。 / p>

答案 3 :(得分:0)

如果您将文件的构建操作设置为要复制,则可以预测文件的位置(可能是一堆.. \ .. \ .. \'但仍然)。我猜你的文件名方法有一个输入,所以应该可以正常工作。

正如一个建议,是否有可能将该文件的实际读取/更改抽象为方法并传递字符串值?我提出这个问题的唯一原因是它闻起来像集成测试(触摸文件系统)。