如何在Scala单元测试中创建临时目录

时间:2019-03-01 14:22:42

标签: scala unit-testing filesystems scalatest

在Scala中,单元测试如何创建一个临时目录以用作测试的一部分?

我正在尝试对依赖于目录的类进行单元测试

class UsesDirectory(directory : java.io.File) {
  ...
}

我正在寻找某种形式的东西:

class UsesDirectorySpec extends FlatSpec {
  val tempDir = ??? //missing piece

  val usesDirectory = UsesDirectory(tempDir)

  "UsesDirectory" should {
    ...
  }
}

此外,在单元测试完成后对适当清理资源的任何评论/建议也将有所帮助。

预先感谢您的考虑和答复。

2 个答案:

答案 0 :(得分:1)

Krzysztof的答案提供了一个很好的策略,可以避免在测试中完全不需要临时目录。

但是,如果您确实需要UsesDirectory来处理真实文件,则可以执行以下操作来创建临时目录:

import java.nio.file.Files
val tempDir = Files.createTempDirectory("some-prefix").toFile

关于清理,您可以使用JVM shutdown钩子机制来删除临时文件。

({java.io.File确实提供了deleteOnExit()方法,但不适用于非空目录)

您可以使用sys.addShutdownHook {}实现自定义的关闭挂钩,并使用Files.walkFiles.walkTree删除临时目录的内容。

您可能还想看看better-files library,它为常见文件操作(包括File.newTemporaryDirectory()file.walk()

)提供了较为简单的scala API

答案 1 :(得分:0)

Java中的

File测试起来非常麻烦。没有简单的方法可以创建可用于测试的虚拟文件系统抽象。

解决这个问题的一种很酷的方法是创建某种包装,可以用于存根和模拟。

例如:

trait FileOps { //trait which works as proxy for file
  def getName(): String
  def exists(): Boolean
}

object FileOps {

  class FileOpsImpl(file: File) extends FileOps {
    override def getName(): String = file.getName //delegate all methods you need
    override def exists(): Boolean = file.exists()
  }

  implicit class FromFile(file: File) { //implicit method to convert File to FileOps
    def toFileOps: FileOpsImpl = new FileOpsImpl(file)
  }
}

然后您必须在课堂上使用它而不是File

class UsesDirectory(directory : FileOps) {
  ...
}

//maybe you can even create implicit conversion, but it's better to do it explicitly
val directory = new UserDirectory(file.toFileOps) 

这有什么好处?

在测试中,您可以提供FileOps的自定义实现:

class UsesDirectorySpec extends FlatSpec {
    val dummyFileOps = new FileOps {
        override def getName(): String = "mock"
        override def exists(): Boolean = true
    }

    //OR

    val mockFileOps = mock[FileOps] //you can mock it easily since it's only trait

    val usesDirectory = UsesDirectory(dummyFileOps)

    "UsesDirectory" should {
      ...
    }
}

如果使用此方法或类似方法,则在单元测试中甚至不需要触摸文件系统。