Форсирование FileNotFoundException - PullRequest
1 голос
/ 03 марта 2009

Я пишу тест для фрагмента кода, в котором есть перехват IOException, который я пытаюсь охватить. Try / catch выглядит примерно так:

try {
    oos = new ObjectOutputStream(new FileOutputStream(cacheFileName));
} catch (IOException e) {
    LOGGER.error("Bad news!", e);
} finally {

Кажется, что самый простой способ заставить FileOutputStream генерировать исключение FileNotFoundException, но, возможно, я иду по этому пути совсем неправильно.

У кого-нибудь есть какие-нибудь советы?

Ответы [ 9 ]

5 голосов
/ 03 марта 2009

Вы можете установить cacheFileName на недопустимое имя или имя, которое, как вы знаете, не существует.

4 голосов
/ 03 марта 2009

Из вашего комментария:

Да, я полагаю, что вопрос должен действительно было "Как мне создать файл, который не существует в обоих Linux и Windows? "На окнах я могу использовать 'Новый файл ("X: /") ", где X: диск письмо, которое не существует. В Linux это не работает, потому что это действительное имя файла.

Посмотрите на java.io.File.createTempFile. Используйте его, чтобы создать файл, а затем удалить его.

Вероятно, передать что-то вроде:

File tempFile;

tempFile = createTempFile(getClass().getName(), 
                          Long.toString(System.currentTimeMillis());
tempFile.delete();

Это должно дать вам уникальное имя в виде отступа на платформе, которое вы можете безопасно использовать, не опасаясь его существа.

2 голосов
/ 03 марта 2009

В любом тесте есть две части: заставить его произойти и измерить, чтобы вы получили правильный результат.

Fault Injection

Самый простой ответ - тот, который уже был упомянут, - установить cacheFileName в файл, который никогда не будет существовать. Это, вероятно, самый практичный ответ в этой ситуации.

Однако, чтобы вызвать произвольное условие, такое как IOException, вам действительно нужно Fault Injection . Это вызывает ошибки в вашем коде, не вынуждая вас использовать ваш исходный код. Вот несколько способов сделать это:

  • Макет объектов Вы можете использовать фабричный метод для создания переопределенных ObjectOutputStream или FileOutputStream. В тестовом коде реализация выдаст IOException, когда вы захотите, а в рабочем коде не изменит нормальное поведение.
  • Внедрение зависимостей Для того, чтобы получить ваш ложный объект в нужном месте, вы можете использовать такие рамки, как Пружина или Шов , чтобы "ввести" соответствующий объект в классе, который делает работу. Вы можете видеть, что эти инфраструктуры даже имеют приоритет для объектов, которые будут внедрены, так что во время модульного тестирования вы можете переопределить производственные объекты тестовыми объектами.
  • Аспектно-ориентированное программирование Вместо того, чтобы вообще изменять структуру вашего кода, вы можете использовать AOP для ввода ошибки в нужное место. Например, используя AspectJ , вы можете определить Pointcut , из которого вы хотите, чтобы было сгенерировано исключение, и Advice сгенерировать нужное исключение.

Есть другие ответы на внедрение ошибок в Java; например, продукт под названием AProbe впервые создал то, что можно было назвать AOP в C, и у них также есть продукт Java.

Проверка

Получение исключения - хорошее начало, но вы также должны подтвердить, что получили правильный результат. Предполагая, что пример кода у вас там правильный, вы хотите проверить, что вы зарегистрировали это исключение. Кто-то выше упомянул об использовании объекта Mock для вашего регистратора, что является приемлемым вариантом. Вы также можете использовать AOP здесь, чтобы перехватить вызов регистратору.

Я предполагаю, что логгер log4j ; Чтобы решить аналогичную проблему, я реализовал свой собственный app4 log4j, который захватывает выходные данные log4j: я специально собираю только ERROR и FATAL, которые, вероятно, будут интересными сообщениями журнала в таком случае. Ссылка на appender указана в log4j.xml и активируется во время тестового прогона для записи выходных данных журнала ошибок. По сути, это фиктивный объект, но мне не пришлось реструктурировать весь мой код, получивший log4j Logger.

0 голосов
/ 03 июля 2012

Надеюсь, это то, что вы имели в виду.

if(new File(cachedFile).exists()) {
    oos = new ObjectOutputStream(new FileOutputStream(cacheFileName));
    //do your code here
} else {
    throw new FileNotFoundException("File doesn't exist!");
}
0 голосов
/ 03 марта 2009
cacheFileName = "thisFileShouldNeverExistAndIfItDoesYouAreScrewingUpMyTests";

Конечно, вы можете делать шаги и прыгать через обруч, чтобы программно убедиться, что имя файла никогда не будет существовать, или вы можете использовать строку, которая никогда не будет существовать в 99,9999% случаев.

0 голосов
/ 03 марта 2009

Поскольку код в настоящее время написан, вы можете попытаться смоделировать вызов error () для объекта LOGGER и проверить, вызывается ли он, когда вы ожидаете IOException.

Ваше желание проверить, возможно, обнаружило фундаментальную проблему с кодом при его написании. Произошла ошибка, но нет логического значения или значения флага (задайте для имени файла специальный шаблон), который предоставляет другие разделы кода для определения успешности записи в файл. Если это содержится в функции, возможно, вы могли бы вернуть логическое значение или установить переменную уровня объекта.

0 голосов
/ 03 марта 2009

Два простых способа: установить cacheFileName в несуществующий файл или установить для указанного файла доступ только для чтения.

-John

0 голосов
/ 03 марта 2009

FileNotFoundException, очевидно, вызовет перехват. В Javadoc указаны случаи, когда он будет брошен.

Также следует учитывать, что конструктор ObjectOutputStream может выдавать IOException, поэтому может потребоваться охватить этот случай в ваших тестах.

0 голосов
/ 03 марта 2009

Я пишу тест для кода у которого есть ловушка IOException что я пытаюсь покрыть.

Я не совсем уверен, что понимаю вашу цель, но если вы хотите проверить, сгенерировано ли исключение, вы можете сказать, что ожидаете, что оно сгенерирует исключение:

@Test(expected=IOException.class)

Ваш тест завершится неудачей, если исключение не было сгенерировано, и завершится успешно, если оно сгенерировано (например, если файл cacheFileName не существует).

...