2013-03-13 77 views
1

我已经成功地使用Specs2来测试文件的序列化,但测试使用了一个真实的文件(写入/ tmp /)。我宁愿不为了测试而接触磁盘。有没有办法使用模拟文件?我可以在Specs2测试中使用模拟文件写入文件吗?如果是这样,怎么样?

def serializeAndDeserializeFromDatafile[X <: CaseClass : Manifest](old: X, maybeGrater: Option[AvroGrater[X]] = None): X = { 
val g = maybeGrater.getOrElse(grater[X]) 

//val outfile = mock[File] 
val outfile = new File("/tmp/file1.avro") 

g.serializeToDataFile(outfile, old) //Serialize to file 

val infile = outfile 
g.asObjectFromDataFile(infile)  //Deserialize from file 
} 

我试着用Mockito来模拟我的outfile(上面的注释行)。在我的天真尝试中,我可以创建Mock for File, hashCode: 1583021903,但在尝试序列化时似乎是null

我想我错过了某种类型的“存根”,但我找不到任何类似的建议解决方案的例子。任何帮助,将不胜感激。

回答

1

我有一个程序(使用Akka自主编写),广泛处理文件系统操作。我使用ScalaIO(而不是本地Java库java.io._类)编写它。除其他外,ScalaIO包括RamFileSystem,它允许您以不涉及文件系统和I/O系统调用的镜像真实文件系统操作的方式来模拟文件系统内容和操作。

+0

太棒了,谢谢。这是我所希望的,但我很快就发现:'val fs = new RamFileSystem(separator =“/”) println(“filesys:”+ fs) val path = fs(“/ tmp /”,'/ “) 的println( “路径:” +路径)的println( “ISFILE ”+ path.isFile) VAL mockedFile = path.createFile() 的println(“ mockedFile” + mockedFile) 的println( “ISFILE” + mockedFile.isFile ) val outfile = mockedFile.fileOption println(“outfile:”+ outfile)'告诉我'mockedFile'是一个文件,但'outfile:Option [File]'是一个'PathType',因此返回'None'而不是所需的'java.io.File' – 2013-03-14 09:09:52

+0

抱歉格式化。 tl; dr:我应该期望能从这种模拟(例如'RamPath')中获得一个'java.io.File'吗? – 2013-03-14 09:14:51

+0

不可以。它必须有一个OS级别的文件系统驱动程序来做到这一点。但是ScalaIO对于I/O和文件操作来说是一个更加丰富的API。 – 2013-03-14 13:37:41

1

你可以尝试使用OutputStream/InputStream而不是文件吗?

例子:

val out:OutputStream = null 
// val testOut = new ByteArrayOutputStream() 
// val realOut = new FileOutputStream(new File("/tmp/file1.avro")) 

g.serializeToOutputStream(out, old) //Serialize to file 

val in:InputStream = null 
// val testIn = new ByteArrayInputStream(testOut.toByteArray) 
// val realIn = new FileInputStream(new File("/tmp/file1.avro")) 

g.asObjectFromInputStream(in)  //Deserialize from file 
+0

谢谢,但我不这么认为:底层类只需要一个'File'。至少它不是很明显*你的建议是如何'模拟'。在使用Specs2来测试这个之前,我试着像你建议的那样“模拟”一个流,但是却试图从没有'datafilereader'的二进制文件中读取记录边界。使用较低级别的Avro类编写avros /看起来非常不同,并且我已经对这种序列化进行了测试。在这里,我需要测试这个组件及其底层高级'datafilewriter/datafilereader'类方法的用法。也许嘲笑那些类呢? – 2013-03-13 09:36:36

+0

嗯,也许我以前的努力并不适用于不适合内存的avros流,但对于这个小测试,我会再试一次......但仍然会喜欢知道如何使用Mockito! – 2013-03-13 09:48:17

1

您可以模拟出一个File但是,这并不意味着事情会好的工作。默认情况下,当您在模拟上调用某个方法时,它会返回null(例如,对于int值,则返回0)。

因此,如果您正在测试的功能调用File方法之一,您将需要提供合理的默认值。例如:

val f = mock[File] 

f.createNewFile returns true 
f.isFile returns true 
f.list returns Array("child1", "child2") 

话虽这么说,如果你的grater对象真正需要的功能性文件写入,它可能真正嘲笑这是不可能的。

+0

这是半回答:)。你能否详细说明'null'来自哪里? – Eric 2013-03-13 12:25:45

+0

这对我来说已经很有用:)我不是专家,所以我现在唯一能够添加'null'的东西就是抛出的错误是'SingleAvroGrater.scala'中的Salat-Avro的序列化异常(主要处理“索引字段”,但不包括文件创建或设置字段的值)。如果我将'mock [File]'的默认返回值设置为'None',那么编译器会抱怨它不能转换为java'Boolean'(我停在那里)。感谢你的例子,我现在看到用这种方式嘲笑有很大的困难,而真正的文件听起来更可接受。并感谢Specs2! – 2013-03-14 08:48:57

相关问题