問題描述
我對模擬還很陌生,我一直在嘗試模擬實際內容(基本上只在內存中創建一個虛擬文件),以便在任何時候都不會將數據寫入磁盤.
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.
我嘗試了一些解決方案,例如模擬文件并模擬盡可能多的屬性,然后使用文件寫入器/緩沖寫入器寫入文件,但這些都不能很好地工作,因為他們需要規范路徑.任何人都找到了除此或類似之外的解決方案,但我正在接近這個錯誤?
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);
}
}
任何想法或指導都會非常有幫助.在此之后的某個地方,我基本上嘗試使用另一個類從文件中讀取.我會嘗試模擬某種輸入流,但另一個類不接受輸入流,因為它是項目的 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.
推薦答案
你似乎在追求矛盾的目標.一方面,您試圖避免將數據寫入磁盤,這在測試中并不是一個壞目標.另一方面,您正在嘗試測試您的 I/O 處理類,這意味著您將使用假定您的 File
將與本機調用一起使用的系統實用程序.因此,這是我的指導:
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
.只是不要.太多原生事物依賴它. - 如果可以,請將您的 I/O 處理代碼分成打開
File
并將其轉換為Reader
的一半,以及解析 HTML 的一半閱讀器
. - 此時,您根本不需要模擬 - 只需構造一個
StringReader
來模擬數據源. - 雖然它可以很好地處理您的單元測試,但您可能還想編寫一個使用 集成測試temp-file-in-java">臨時文件 并確保它讀取正確.(感謝 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!)
不要害怕重構你的類以使測試更容易,如下所示:
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));
}
}
此時 method
中的邏輯非常簡單,不值得測試,methodForTest
中的邏輯非常容易訪問,您可以對其進行大量測試.
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.
這篇關于在 Java 中模擬文件 - 模擬內容 - Mockito的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!