問(wèn)題描述
我對(duì)模擬還很陌生,我一直在嘗試模擬實(shí)際內(nèi)容(基本上只在內(nèi)存中創(chuàng)建一個(gè)虛擬文件),以便在任何時(shí)候都不會(huì)將數(shù)據(jù)寫(xiě)入磁盤(pán).
I'm pretty new to mocking, and I've been trying to mock the actual contents (essentially create a virtual file in memory alone) so that no data is written to disk at any point.
我嘗試了一些解決方案,例如模擬文件并模擬盡可能多的屬性,然后使用文件寫(xiě)入器/緩沖寫(xiě)入器寫(xiě)入文件,但這些都不能很好地工作,因?yàn)樗麄冃枰?guī)范路徑.任何人都找到了除此或類似之外的解決方案,但我正在接近這個(gè)錯(cuò)誤?
I've tried solutions like mocking the file and mocking as many of the properties that I can figure out as much as possible, an then also writing into it with a filewriter/bufferedwriter, but those don't work well, since they need canonical paths. Anyone found a solution other than this or similar, but that I'm approaching this wrong?
我一直是這樣的:
private void mocking(){
File badHTML = mock(File.class);
//setting the properties of badHTML
when(badHTML.canExecute()).thenReturn(Boolean.FALSE);
when(badHTML.canRead()).thenReturn(Boolean.TRUE);
when(badHTML.canWrite()).thenReturn(Boolean.TRUE);
when(badHTML.compareTo(badHTML)).thenReturn(Integer.SIZE);
when(badHTML.delete()).thenReturn(Boolean.FALSE);
when(badHTML.getFreeSpace()).thenReturn(0l);
when(badHTML.getName()).thenReturn("bad.html");
when(badHTML.getParent()).thenReturn(null);
when(badHTML.getPath()).thenReturn("bad.html");
when(badHTML.getParentFile()).thenReturn(null);
when(badHTML.getTotalSpace()).thenReturn(0l);
when(badHTML.isAbsolute()).thenReturn(Boolean.FALSE);
when(badHTML.isDirectory()).thenReturn(Boolean.FALSE);
when(badHTML.isFile()).thenReturn(Boolean.TRUE);
when(badHTML.isHidden()).thenReturn(Boolean.FALSE);
when(badHTML.lastModified()).thenReturn(System.currentTimeMillis());
when(badHTML.mkdir()).thenReturn(Boolean.FALSE);
when(badHTML.mkdirs()).thenReturn(Boolean.FALSE);
when(badHTML.setReadOnly()).thenReturn(Boolean.FALSE);
when(badHTML.setExecutable(true)).thenReturn(Boolean.FALSE);
when(badHTML.setExecutable(false)).thenReturn(Boolean.TRUE);
when(badHTML.setReadOnly()).thenReturn(Boolean.FALSE);
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(badHTML));
/*
badHTMLText is a string with the contents i want to put into the file,
can be just about whatever you want
*/
bw.append(badHTMLText);
bw.close();
} catch (IOException ex) {
System.err.println(ex);
}
}
任何想法或指導(dǎo)都會(huì)非常有幫助.在此之后的某個(gè)地方,我基本上嘗試使用另一個(gè)類從文件中讀取.我會(huì)嘗試模擬某種輸入流,但另一個(gè)類不接受輸入流,因?yàn)樗琼?xiàng)目的 io 處理類.
Any ideas or guidance would be very helpful. Somewhere after this i basically try to read from the file using another class. I would try to mock some sort of input stream, but the other class doesn't take an inputstream, since it's the io handling class for the project.
推薦答案
你似乎在追求矛盾的目標(biāo).一方面,您試圖避免將數(shù)據(jù)寫(xiě)入磁盤(pán),這在測(cè)試中并不是一個(gè)壞目標(biāo).另一方面,您正在嘗試測(cè)試您的 I/O 處理類,這意味著您將使用假定您的 File
將與本機(jī)調(diào)用一起使用的系統(tǒng)實(shí)用程序.因此,這是我的指導(dǎo):
You seem to be after contradictory goals. On the one hand, you're trying to avoid writing data to disk, which isn't a bad goal in tests. On the other, you're trying to test your I/O-handling class, which means you'll be working with system utilities that assume that your File
will work with native calls. As such, here's my guidance:
- 不要試圖模擬
File
.只是不要.太多原生事物依賴它. - 如果可以,請(qǐng)將您的 I/O 處理代碼分成打開(kāi)
File
并將其轉(zhuǎn)換為Reader
的一半,以及解析 HTML 的一半閱讀器
. - 此時(shí),您根本不需要模擬 - 只需構(gòu)造一個(gè)
StringReader
來(lái)模擬數(shù)據(jù)源. - 雖然它可以很好地處理您的單元測(cè)試,但您可能還想編寫(xiě)一個(gè)使用 集成測(cè)試temp-file-in-java">臨時(shí)文件 并確保它讀取正確.(感謝 Brice 添加提示!)
- Don't try to mock a
File
. Just don't. Too many native things depend on it. - If you can, split your I/O-handling code into the half that opens a
File
and turns it into aReader
, and the half that parses HTML out of theReader
. - At that point, you don't need a mock at all--just construct a
StringReader
to simulate the data source. - While that handles your unit tests pretty well, you may also want to write an integration test that uses a temporary file and ensure that it reads right. (Thanks Brice for adding that tip!)
不要害怕重構(gòu)你的類以使測(cè)試更容易,如下所示:
Don't be afraid to refactor your class to make testing easier, as here:
class YourClass {
public int method(File file) {
// do everything here, which is why it requires a mock
}
}
class YourRefactoredClass {
public int method(File file) {
return methodForTest(file.getName(), file.isFile(),
file.isAbsolute(), new FileReader(file));
}
/** For testing only. */
int methodForTest(
String name, boolean isFile, boolean isAbsolute, Reader fileContents) {
// actually do the calculation here
}
}
class YourTest {
@Test public int methodShouldParseBadHtml() {
YourRefactoredClass yrc = new YourRefactoredClass();
assertEquals(42, yrc.methodForTest(
"bad.html", true, false, new StringReader(badHTMLText));
}
}
此時(shí) method
中的邏輯非常簡(jiǎn)單,不值得測(cè)試,methodForTest
中的邏輯非常容易訪問(wèn),您可以對(duì)其進(jìn)行大量測(cè)試.
At this point the logic in method
is so straightforward it's not worth testing,
and the logic in methodForTest
is so easy to access that you can test it heavily.
這篇關(guān)于在 Java 中模擬文件 - 模擬內(nèi)容 - Mockito的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!