代码之家  ›  专栏  ›  技术社区  ›  chester89

如何将单元测试文件保存到磁盘?

  •  21
  • chester89  · 技术社区  · 16 年前

    我知道强烈建议运行单元测试 与文件系统分离
    我的问题是,如果我想测试文件保存到磁盘,我该怎么做?和数据库一样,我分离了一个负责数据库访问的接口,然后为我的测试创建了另一个实现?或者有别的办法?

    3 回复  |  直到 16 年前
        1
  •  44
  •   Lernkurve    12 年前

    我对这一点的态度严重偏向于 Growing Object-Oriented Software Guided by Tests

    • 创建一个接口,将文件系统从代码中抽象出来。在需要将此类作为协作者/依赖项的情况下对其进行模拟。这可以让你的单元测试和反馈更快。
    • 创建一个端到端测试整个系统的验收测试。在这里,您可以验证是否创建了一个文件—此测试的目的是确认实际实现是否正确连接/插入。

    评论者更新:

    如果您正在读取结构化数据(例如图书对象)(如果不是,请用字符串代替IEnumerable)

    interface BookRepository
    {
      IEnumerable<Books> LoadFrom(string filePath);
      void SaveTo(string filePath, IEnumerable<Books> books);
    }
    

    所以你很快; 不要攻击文件系统 . 它们只是验证是否对依赖项调用了正确的方法(例如加载/保存)

    var testSubject = new Client(new Mock<BookRepository>.Object);
    

    下一步,您需要创建BookRepository的真正实现,该实现可以在文件上工作(如果需要的话,也可以在明天创建sqldb)。其他人不必知道。 写 对于FileBasedBookRepository(实现上述角色)并测试调用Load with a reference file会给出正确的对象,调用Save with a known list会将它们持久化到磁盘。即 使用真实文件

    [TestFixture]
    [Category("Integration - Slow")]
    public class FileBasedBookRepository 
    {
      [Test]
      public void CanLoadBooksFromFileOnDisk() {...}
      [Test]
      public void CanWriteBooksToFileOnDisk() {...}
    }
    

    验收试验 锻炼负重和节省。

        2
  •  6
  •   Mark Byers    16 年前

    您可以传递流、TextWriter或类似的文件,而不是将文件名传递给save函数。然后在测试时,您可以通过一个基于内存的实现,并验证是否写入了正确的字节,而无需实际向磁盘写入任何内容。

        3
  •  4
  •   Raedwald    12 年前

    编写执行文件I/O的单元测试时,有一条一般规则需要谨慎,因为它们往往太慢。但在单元测试中并没有绝对禁止文件I/O。

    @Rule TemporaryFolder .

    1. 打开文件的输出流。此代码必须处理丢失的文件或文件权限问题。您需要测试它是否打开文件并处理这些失败条件。
    2. 关闭输出流。这必须在关闭流时处理I/O错误,尽管这些错误在实践中很少见。

    只有第一个真正涉及文件系统。其余的只使用一个输出流。

    因此,您可以将中间部分和最后一部分提取到它自己的方法(函数),该方法处理给定的输出流,而不是命名文件。然后可以模拟输出流来对方法进行单元测试。这些单元测试将非常快。大多数编程语言已经提供了一个合适的输出流类。

    这只剩下第一部分需要单元测试。您将只需要几个测试,所以您的测试套件应该仍然可以接受的快。