2010-04-02 14 views
17

Mam fragment kodu, który odczytuje dane z pliku. Chcę wymusić wyjątek IOException w tym kodzie do celów testowych (chcę sprawdzić, czy kod zgłasza w tym przypadku poprawny niestandardowy wyjątek).Wymusza wyjątek IOException podczas odczytu pliku

Czy istnieje sposób na utworzenie pliku, który jest chroniony przed odczytaniem, na przykład? Być może radzenie sobie z niektórymi kontrolami bezpieczeństwa może pomóc?

Należy pamiętać, że podanie nazwy nieistniejącego pliku nie może pomóc, ponieważ FileNotFoundException ma osobną klauzulę catch.

Oto fragment kodu dla lepszego zrozumienia kwestii:

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

Można spróbować czytania pliku, że nie wolno nam czytać. W systemie Linux '/ proc/kcore' jest dobrym wyborem, podobnie jak'/etc/shadow'. –

+1

nie jest odpowiedzią, ale spostrzeżeniem. Powinieneś owinąć wyjątek IOException niestandardowym wyjątkiem, aby zachować pełne śledzenie stosu. tj. "throw new SomeCusomException (e)" –

Odpowiedz

-1

zawsze można rzucić własne IOException:

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

Dodałem kod oryginalnego pytania. Wygląda na to, że tego nie rozumiesz. – DixonD

0

Można zrobić wyjątek ten podnieść do pliku, który jest zbyt duży.

2

Możesz spróbować utworzyć plik jako superużytkownik, a następnie odczytać go jako standardowy użytkownik. Tam powinny być problemy z uprawnieniami. Lub po prostu chmod, zakładając, że jesteś na Linuksie. Możesz także spróbować umieścić go w ukrytym/chronionym katalogu.

+0

Czy możesz podać przykład, który zadziała na dowolnym docelowym systemie operacyjnym? – DixonD

+3

Ponieważ systemy operacyjne różnią się dość drastycznie pod względem tego, co robią z systemami plików i zarządzaniem użytkownikami, jest to trudne. Możesz spróbować użyć obiektu plików Java i wywołać na nim zbiór setReadable/setWritable - patrz http://java.sun.com/javase/6/docs/api/java/io/File.html#setReadable%28boolean%29 –

+1

Niesamowicie sprytna odpowiedź. Jest nawet wieloplatformowy. Nie wymaga ram szyderczych innych firm. Powinna być zaakceptowaną odpowiedzią, jeśli mnie zapytasz. – jontejj

4

Jeśli możesz nieznacznie zmienić kod, aby zaakceptować czytnik, a nie nazwę pliku, możesz użyć makiet. Z EasyMock możesz stworzyć fałszywego Reader'a i ustawić go tak, by rzucił wyjątek IOException po wywołaniu dowolnej z jego metod. Wtedy po prostu przekazać je do metody należy badać i obserwować co się dzieje :-)

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 
      } 
     } 
    } 
} 

następnie kodu testu:

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

objectToTest.readFile(reader); 
+0

Szkoda, że ​​nie mogę zmienić testowanego kodu – DixonD

+1

@DixonD: jeśli nie możesz go zmienić, a nie jest on poprawnie zaprojektowany, nie możesz go przetestować w jednostce. Najlepsze, co możesz mieć nadzieję, to przeprowadzenie testów integracyjnych. –

1

można użyć Mock bibliotekę jak Mockito lub Easymock (+classpath) stworzyć obiekt Mock file (nowsze biblioteki mają rozszerzenia classloader, które umożliwiają kategoryzowanie konkretnych klas, takich jak File), lub mogą współpracować z czymś takim jak PowerMock (see blog) i mieć fałszywe wygenerowane dla wywołania konstruktora, i wyrzucić odpowiedni wyjątek, gdy zostanie wywołany.

+0

Nie ma sposobu, aby przekazać próbę w kodzie – DixonD

+0

Edytowano odpowiedź na link do wpisu blogu o użyciu PowerMock do tego rodzaju testów (wykorzystuje manipulację ClassLoader) – jayshao

7

Nota prawna: Nie testowałem tego na platformie innej niż Windows, więc może mieć różne wyniki na platformie z różnymi charakterystykami blokowania plików.

Jeśli zablokować plik wcześniej, można wywołać IOException, gdy coś próbuje odczytać z niego:

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

Działa to nawet, jeśli w tym samym wątku.

Oto niektóre przykładowy kod:

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

Nie działa dla mnie - przy użyciu Ubuntu .. ale pomysł jest miło :) –

+0

działa w systemie Windows – panny

1

Można wymusić wyjątek poprzez wywołanie metody close na swojej BufferedReader:

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

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

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

Mam nadzieję, że pomaga.

0

Polecam przeciwko użyciu wyjątku FileNotFoundException. Jeśli chcesz rzucić określony wyjątek dla nieistniejącego pliku, sprawdziłbym csvFile.exists().

Na przykład można wykonać katalog o wartości csvFile. Przetestowałem kod i rzucił:

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

W mojej opinii, plik rzeczywiście jest katalog nie jest taki sam jak FileNotFound, ale to działa tak samo w Javie.

0

Zdefiniuj w teście przeciążenia FileInputStream że zgłasza wyjątek

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); 
} 
Powiązane problemy