Вопрос

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

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

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

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

Это было полезно?

Решение

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

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

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

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

File tempFile;

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

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

Другие советы

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

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

Внесение ошибок

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

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

  • Макетные объекты Вы можете использовать фабричный метод для создания переопределенного ObjectOutputStream или FileOutputStream.В тестовом коде реализация выдаст IOException когда вы этого захотите, и в рабочем коде не изменится нормальное поведение.
  • Внедрение зависимости Чтобы разместить свой Mock Object в нужном месте, вы можете использовать такую ​​структуру, как Весна или Шов «внедрить» соответствующий объект в класс, выполняющий работу.Вы можете видеть, что эти платформы даже имеют приоритет для объектов, которые будут внедрены, так что во время модульного тестирования вы можете переопределить производственные объекты тестовыми объектами.
  • Аспектно-ориентированное программирование Вместо того, чтобы вообще менять структуру вашего кода, вы можете использовать АОП для внесения ошибки в нужное место.Например, используя АспектJ вы могли бы определить Пойнткат откуда вы хотели, чтобы было выброшено исключение, и иметь Совет выдать желаемое исключение.

Есть и другие ответы на внесение ошибок в Java;например, продукт под названием AПроб давным-давно стали пионерами того, что можно было бы назвать АОП на языке C, а также у них есть продукт на языке Java.

Проверка

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

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

Я пишу тест на кусок кода, в котором есть улов в ioException, которое я пытаюсь осветить.

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

@Test(expected=IOException.class)

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

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

Вам также следует учитывать, что конструктор ObjectOutputStream может генерировать исключение IOException, поэтому, возможно, вы захотите охватить этот случай в своих тестах.

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

-Джон

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

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

cacheFileName = "thisFileShouldNeverExistAndIfItDoesYouAreScrewingUpMyTests";

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

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

if(new File(cachedFile).exists()) {
    oos = new ObjectOutputStream(new FileOutputStream(cacheFileName));
    //do your code here
} else {
    throw new FileNotFoundException("File doesn't exist!");
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top