使用File.OpenRead()对类进行单元测试

时间:2017-11-07 12:38:18

标签: c# unit-testing moq

我想测试一个使用方法File.OpenRead()来获取文件内容的类。在读取文件的内容后,它会处理它们。我创建了一个接口和一个包装静态OpenRead()方法的类。但是我遇到OpenRead()返回FileStream但我不知道如何“模拟”文件流的问题。

目前,我正在创建一个文件,只是为了创建一个FileStream ...当然,测试经常会失败IOException,因为该文件仍在使用中......

剥离示例: 类:

class FileProcessor
{
  public FileProcessor(IFileWrap fileWrap) // fileWrap only redirects the calls to the static methods of File class
  { ... }

  public void Process(string file)
  {
    var content = fileWrap.ReadAllLines(file);

    // process content
  }
}

测试:

[TestClass]
public class FileProcessor_Test
{
  [TestMethod]
  Process_FileNotReadable_Exception()
  {
    File.WriteAllText(testFile, "something");
    var fileWrapMock = new Mock<IFileWrap>();
    FileProcessor dut = new FileProcessor(fileWrapMock.Object);
    var actualException = AssertException.Throws<Exception>(() => dut.Process(testFile));
  }
}

我也想避免创建FileStream的抽象。

我希望我可以创建一个MemoryStream并以某种方式将其用作输入,但这需要更改文件包装并偏离实际的File类。

赞赏任何意见:)

编辑: 处理包括通过从类ComputeHash()调用MD5来计算MD5校验和。

3 个答案:

答案 0 :(得分:4)

您的原始方法与它在文件上运行的事实紧密相关。不要这样做。使方法采用Stream任何流。您可以使用FileStream进行操作,也可以通过MemoryStream进行测试。

public void Process(string file)

应该是

public void Process(Stream stream)

如果您愿意,为方便起见,您可能会有第二个方法重载:

public void Process(string file)
{
    using (var stream = new FileStream(file, FileMode.Open))
    {
        this.Process(stream);
    }
}

确实不能也不应该进行单元测试......它的.NET代码处理外部资源,在某些时候你必须信任框架。

要解决您的编辑问题:大多数Framework类都做类似的事情,例如MD5类有一个适用于流的ComputeHash方法。

答案 1 :(得分:2)

首先,您不需要进行单元测试&#39;文件&#39;作为&#39; OpenRead&#39;是一个静态的方法&#39; File&#39;你无法解耦的阶级。对任何具有依赖性的东西编写单元测试并不理想。在你的情况下,你可以模拟&#39; IFileWrap&#39;并为'ReadAllLines&#39;创建一个模拟方法。当单元测试命中&fileWrap.ReadAllLines(文件)&#39;它会调用mock方法而不是去#File; Openpen()&#39;方法

答案 2 :(得分:1)

我建议你让IFileWrap返回一个字符串(读取所有行)而不是MemoryStream。基本上,可以在File上创建一个抽象,将File封装在其中。