Как мне написать модульный тест, чтобы покрыть случай, когда выбрасывается IOException? - PullRequest
5 голосов
/ 15 июля 2011

У меня есть следующий класс:

    public class FileLoader {   

         private Map<Brand, String> termsOfUseText = new HashMap<Brand, String>();

         public void load() {
            for (Brand brand : Brand.values()) {
                readAndStoreTermsOfUseForBrand(brand);
            }
         }

         private void readAndStoreTermsOfUseForBrand(Brand brand) {
            String resourceName = "termsOfUse/" + brand.name().toLowerCase() + ".txt";          
            InputStream in = this.getClass().getClassLoader().getResourceAsStream(resourceName);            
            try {
                String content = IOUtils.toString(in);          
                termsOfUseText.put(brand, content);
            } catch (IOException e) {
                throw new IllegalStateException(String.format("Failed to find terms of use source file %s", resourceName),e);
            }
         }

        public String getTextForBrand(Brand brand) {
            return termsOfUseText.get(brand);
        }
    }

Бренд - это перечисление, и мне нужно, чтобы все допустимые файлы .txt были в пути к классам. Как заставить IOException возникнуть, учитывая, что перечисление Brand содержит все действительные бренды и, следовательно, все файлы .txt для них существуют?

Предложения по рефакторингу текущего кода приветствуются, если он делает его более тестируемым!

Ответы [ 4 ]

3 голосов
/ 15 июля 2011

Три варианта, которые я вижу сразу:

  1. Используйте PowerMock для насмешки IOUtils.toString (). Я считаю PowerMock как последнее средство. Я бы предпочел рефакторинг источника на что-то более удобное для тестирования.
  2. Извлечение вызова IOUtils для защищенного метода. Создайте специфичный для теста подкласс вашего класса, который переопределяет этот метод и вызывает исключение IOException.
  3. Извлечение создания InputStream в защищенный метод. Создайте специфичный для теста подкласс для переопределения метода и возврата фиктивного InputStream.
0 голосов
/ 14 октября 2015

Я бы использовал макет для этого.

Пример (непроверенный, просто чтобы подумать):

@Test(expected=IllegalStateException.class)
public void testThrowIOException() {
    PowerMockito.mockStatic(IOUtils.class);
    PowerMockito.when(IOUtils.toString()).thenThrow(
             new IOException("fake IOException"));
    FileLoader fileLoader = new FileLoader();
    Whitebox.invokeMethod(fileLoader, 
            "readAndStoreTermsOfUseForBrand", new Brand(...));
    // If IllegalStateException is not thrown then this test case fails (see "expected" above)
}
0 голосов
/ 15 июля 2011

Код ниже полностью не проверен
Чтобы вызвать IOException, используйте:

FileInputStream in = this.getClass().getClassLoader().getResourceAsStream(resourceName);
in.mark(0);  
//read some data
in.reset(); //IOException

Для проверки случая IOException используйте:

void test  
{  
    boolean success = false;  
    try  
    {  
      //code to force ioException  
    }  
    catch(IOException ioex)  
    {  
       success = true;  
    }  
    assertTrue(success);  
}

В JUnit4

@Test(expected=IOException.class)  
void test  
{  
   //code to force ioException  
}

Другой JUnit

void test  
{  
   try  
   {  
     //code to force IOException  
     fail("If this gets hit IO did not occur, fail test");  
   }
   catch(IOException ioex)  
   {
    //success!
    }  
}
0 голосов
/ 15 июля 2011

Отсутствующий файл вызовет NullPointerException, потому что getResourceAsStream вернет null и у вас будет in==null. IOException в этом случае может быть довольно редким. Если вам важно это увидеть, я могу думать только о том, чтобы оснастить этот код, если он выполняется в тестовой области. Но так ли это важно?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...