2010-04-02 64 views
17

我有一段從文件讀取數據的代碼。我想在此代碼中強制執行IOException以進行測試(我想在此例中檢查代碼是否引發正確的自定義異常)。讀取文件時強制IOException

有沒有什麼辦法可以創建一個文件,防止被讀取,例如?也許處理一些安全檢查可以提供幫助?

請注意,傳遞一個不存在的文件的名字是無濟於事的,因爲FileNotFoundException有一個單獨的catch子句。

這裏是爲了更好地理解問題的一段代碼:

BufferedReader reader = null; 
    try { 

     reader = new BufferedReader(new FileReader(csvFile)); 

     String rawLine; 
     while ((rawLine = reader.readLine()) != null) { 
      // some work is done here 
     } 

    } catch (FileNotFoundException e) { 
     throw new SomeCustomException(); 
    } catch (IOException e) { 
     throw new SomeCustomException(); 
    } finally { 
     // close the input stream 
     if (reader != null) { 
      try { 
       reader.close(); 
      } catch (IOException e) { 
       // ignore 
      } 
     } 
    } 
+0

你可以嘗試閱讀,你不能讀取文件。在Linux上'/ proc/kcore'是一個很好的選擇,就像'/ etc/shadow'一樣。 – 2011-07-25 12:21:20

+1

不是一個答案,而是一個觀察。您應該使用您的自定義異常來封裝IOException以保留完整的堆棧跟蹤。即'拋出SomeCusomException(e)' – 2012-10-12 20:51:08

回答

-1

您可以隨時拋出自己的IOException

throw new IOException("Test IOException"); 
+0

我添加了原始問題的代碼。看來你並不瞭解它。 – DixonD 2010-04-02 13:10:56

0

你可以把這個異常募集的文件說的太大。

2

您可以嘗試以超級用戶身份創建文件,然後將其作爲標準用戶閱讀。那裏應該有權限問題。或者只是假設你在Linux上進行chmod操作。您也可以嘗試將其放置在隱藏/受保護的目錄中。

+0

你能提供一個適用於任何目標操作系統的例子嗎? – DixonD 2010-04-02 13:13:13

+3

由於操作系統在文件系統和用戶管理方面的差異很大,所以很困難。您可以嘗試使用java File對象並調用setReadable/setWritable - 請參閱http://java.sun.com/javase/6/docs/api/java/io/File.html#setReadable%28boolean%29 – 2010-04-02 13:46:40

+1

令人難以置信聰明的回答。它甚至是跨平臺的。它不需要第三方模擬框架。如果你問我,應該是被接受的答案。 – jontejj 2013-06-07 18:04:27

4

如果您可以稍微重構代碼以接受Reader而不是文件名,則可以使用mocks。通過EasyMock,您可以創建一個模擬Reader,並將其設置爲在調用您希望的任何方法時拋出IOException。然後你只需將它傳遞給方法進行測試,並看看會發生什麼:-)

void readFile(Reader reader) throws SomeCustomException { 
    try { 
     String rawLine; 
     while ((rawLine = reader.readLine()) != null) { 
      // some work is done here 
     } 

    } catch (FileNotFoundException e) { 
     throw new SomeCustomException(); 
    } catch (IOException e) { 
     throw new SomeCustomException(); 
    } finally { 
     // close the input stream 
     if (reader != null) { 
      try { 
       reader.close(); 
      } catch (IOException e) { 
       // ignore 
      } 
     } 
    } 
} 

然後測試代碼:

mockReader = createMock(Reader.class); 
expect(mockReader.readLine()).andThrow(
     new IOException("Something terrible happened")); 
replay(mockReader); 

objectToTest.readFile(reader); 
+0

很遺憾,我無法更改測試代碼 – DixonD 2010-04-02 13:16:14

+1

@DixonD:如果您無法更改它,並且設計不正確,則無法對其進行單元測試。你可以期望的最好的做法是做一些集成測試。 – 2011-07-25 12:19:24

1

您可以使用像MockitoEasymock (+classpath)一個模擬庫創建一個Mock文件對象(新的libs有類加載器擴展,可以讓你模擬具體的類如File),或者可以配合類似於PowerMock (see blog)的類,併爲構造函數調用生成一個模擬對象,並在調用時拋出相應的異常。

+0

沒有辦法在代碼中傳遞模擬 – DixonD 2010-04-04 16:16:08

+0

編輯鏈接到使用PowerMock進行此類測試的博客條目的答案(利用ClassLoader操作) – jayshao 2010-04-05 15:25:29

7

聲明:我沒有在非Windows平臺上測試過,所以它在具有不同文件鎖定特徵的平臺上可能會有不同的結果。

如果你事先鎖定文件,你可以在一些試圖從中讀取觸發一個IOException:

java.io.IOException: The process cannot access the file because another process has locked a portion of the file 

這工作,即使你是在同一個線程。

下面是一些示例代碼:

final RandomAccessFile raFile = new RandomAccessFile(csvFile, "rw"); 
raFile.getChannel().lock(); 
+2

不適用於我 - 使用Ubuntu ..但這個想法很好:) – 2012-07-11 20:21:55

+0

在windows上工作 – panny 2013-03-18 04:20:19

1

你可以通過調用你的BufferedReader Close方法強制異常:

reader = new BufferedReader(new FileReader(csvFile)); 

    // invoke the Close() method. 
    reader.Close(); 

    String rawLine; 
    while ((rawLine = reader.readLine()) != null) { 
     // some work is done here 
    } 

我希望幫助。

0

我建議不要使用FileNotFoundException。如果你想爲不存在的文件拋出特定的異常,我會檢查csvFile.exists()。

例如,你可以製作csvFile的一個目錄。我測試你的代碼,並把它扔到:

File file = new File("actually_a_directory.csv"); file.mkdir(); yourCode(file); // throws FileNotFoundException: "actually_a_directory.csv (Access is denied)"

在我看來,其實是一個文件的目錄是不一樣的FileNotFound,但它的行爲同樣在java中。

0

定義在您的測試超載的FileInputStream拋出異常

FileInputStream s; 
try { 
    s = new FileInputStream(fileName) { 

      @Override 
      public int read() throws IOException { 
       throw new IOException("Expected as a test"); 
      } 
     }; 
} catch (FileNotFoundException e) { 
    throw new RuntimeException(e.getMessage(), e); 
}