Сила IOException во время чтения файла

17

У меня есть фрагмент кода, который считывает данные из файла. Я хочу заставить 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
            }
        }
    }
    
задан DixonD 02.04.2010 в 15:03
источник
  • Вы можете попробовать прочитать файл, который вам не разрешено читать. В Linux / proc / kcore хорошая ставка, равно как и / etc / shadow. –  Joachim Sauer 25.07.2011 в 14:21
  • не ответ, а наблюдение. Вы должны обернуть IOException своим пользовательским Исключением, чтобы сохранить полную трассировку стека. то есть выбросить новое исключение SomeCusomException (e) –  Steve Atkinson 12.10.2012 в 22:51

9 ответов

8

Отказ от ответственности: я не тестировал это на платформе, отличной от 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();
    
ответ дан Weston B 25.07.2011 в 14:00
  • Не работает для меня - с помощью Ubuntu .. но идея хорошая :) –  Bertram Nudelbach 11.07.2012 в 22:21
  • работает над окнами –  panny 18.03.2013 в 05:20
4

Если вы можете реорганизовать код немного, чтобы принять Reader, а не имя файла, вы можете использовать mocks. С помощью EasyMock вы можете создать mock 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);
    
ответ дан Péter Török 02.04.2010 в 15:07
  • Жаль, что я не могу изменить проверенный код –  DixonD 02.04.2010 в 15:16
  • @DixonD: если вы не можете изменить его, и он не разработан правильно, вы не можете его выполнить. Самое лучшее, на что вы можете надеяться, - это провести интеграционное тестирование. –  Joachim Sauer 25.07.2011 в 14:19
2

Вы можете попробовать создать файл в качестве суперпользователя, а затем прочитать его как стандартного пользователя. Там должны быть проблемы с разрешениями. Или просто chmod, предполагая, что вы работаете в Linux. Вы также можете попробовать поместить его в скрытый / защищенный каталог.

    
ответ дан NG. 02.04.2010 в 15:06
  • Можете ли вы привести пример, который будет работать на любой целевой ОС? –  DixonD 02.04.2010 в 15:13
  • Поскольку операционные системы сильно отличаются друг от друга с точки зрения того, что они делают с файловыми системами и управлением пользователями, это сложно. Вы можете попробовать использовать объект Java Java и вызвать setReadable / setWritable на нем - см. Java.sun.com/javase/6/docs/api/java/io/... –  NG. 02.04.2010 в 15:46
  • Невероятно умный ответ. Это даже кросс-платформенный. Это не требует сторонней издевательской структуры. Должен быть принятый ответ, если вы спросите меня. –  jontejj 07.06.2013 в 20:04
1

Вы можете использовать библиотеку Mock, например Mockito или Easymock (+ classpath ) для создания объекта Mock-файла (у более новых библиотек есть расширения класса-загрузчика, которые позволяют вам издеваться над конкретными классами, например File), или могут взаимодействовать с чем-то вроде PowerMock (см. Блог) , и для создания вызова конструктора создается ложная генерация, а при вызове вызывается соответствующее исключение.

    
ответ дан jayshao 02.04.2010 в 23:24
  • Невозможно передать макет кода –  DixonD 04.04.2010 в 18:16
  • Отредактировал ответ на ссылку на запись в блоге по использованию PowerMock для такого тестирования (использует манипуляции ClassLoader) –  jayshao 05.04.2010 в 17:25
1

Вы можете вызвать исключение, вызвав метод close на 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
    }

Я надеюсь, что это поможет.

    
ответ дан nsanzeri 12.10.2012 в 19:40
0

Вы можете сделать это повышение уровня для слишком большого файла.

    
ответ дан thelost 02.04.2010 в 15:06
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.

    
ответ дан River 19.08.2016 в 00:19
0

Определите в своем тесте перегруженный файлInputStream, который генерирует исключение

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);
}
    
ответ дан Jeroen Heemskerk 24.08.2016 в 15:36
-1

Вы всегда можете бросить свой собственный IOException :

throw new IOException("Test IOException");
    
ответ дан Adam Batkin 02.04.2010 в 15:05
  • Я добавил код для оригинального вопроса. Кажется, вы этого не поняли. –  DixonD 02.04.2010 в 15:10