2013-03-13 72 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

相關問題