2016-12-12 4 views
2

Я написал тестовый пример Junit для следующей функции. При проверке покрытия JACOCO. Он показывает, что только тестовый блок покрывается тестовым случаем. Я новичок в написании тестовых примеров. Как блок исключения и улов может быть покрыт в тестовыхНаписание теста Junit для исключения исключения и блока catch

Вот метод

public static List<Student> readCsvFile(String fileName) 
    { 

     BufferedReader fileReader = null; 

//logic to read file  
} 
catch (Exception e) 
{ 
    System.out.println("Error in CsvFileReader !!!"); 
    e.printStackTrace(); 
     } finally 
     { 
      try 
      { 
       fileReader.close(); 
      } catch (IOException e) 
      { 
       System.out.println("Error while closing fileReader !!!"); 
       e.printStackTrace(); 
      } 
     } 
     return students; 
    } 

И TestMethod

@Test 
    public void ReadCsvFileTest() 
    { 
     String fileName = "test.csv"; 
     List<Student> result = new ArrayList<Student>(); 
     result = CsvFileReader.readCsvFile(fileName); 

     Student student1 = null; 

     Iterator<Student> it = result.iterator(); 
     while (it.hasNext()) 
     { 
      Student s = it.next(); 
      if ("471908US".equals(s.getId())) 
      { 
       student1 = s; 
       break; 
      } 
     } 

     assertTrue(student1 != null); 
    } 
+1

Вы получите только покрытие для блока исключений, если выбрано исключение. – Compass

+1

'CsvFileReader.readCsvFile (" notexisting.csv ")' должен ввести catch –

+1

Поскольку Compass рекомендует вам вызывать исключение внутри блока try во время выполнения теста. Обычно я использовал бы насмешливую структуру, такую ​​как Mockito, чтобы достичь этого. Но, возможно, в вашем случае его достаточно, чтобы передать недопустимое имя файла. – morgelo

ответ

2

В таких ситуациях вы можете часто учитывать введение дополнительных зависимостей в ваш класс. Вот что я имею в виду с примерным примером. Создать завод для считывателей:

interface BufferedReaderFactory 
{ 
    public BufferedReader createBufferedReader(String fileName) throws IOException; 
} 

Тогда у вас будет тривиальная реализация, которая вряд ли нуждается в каком-либо тестировании, например. что-то похожее:

class BufferedReaderFactoryImpl implements BufferedReaderFactory 
{ 
    @Override 
    public BufferedReader createBufferedReader(String fileName) throws IOException 
    { 
     return new BufferedReader(new FileReader(fileName)); 
    } 
} 

Затем вы должны найти способ ввести эту зависимость в свой класс. Обычно я использую Guice в своей повседневной работе, но вы можете попробовать что-то так же просто, как использовать инъекцию конструктора и сделать ваш метод не статическим.Вот пример:

class CsvFileReader 
{ 
    private final BufferedReaderFactory factory; 

    public CsvFileReader(BufferedReaderFactory factory) 
    { 
     this.factory = factory; 
    } 

    public List<Student> readCsvFile(String fileName) 
    { 

     BufferedReader fileReader = null; 
     try 
     { 
      fileReader = factory.createBufferedReader(fileName); 
      ... 
     } 
     catch(IOException e) 
     { 
      ... 
     } 
     finally 
     { 
      ... 
     } 
     return new LinkedList<>(); 
    } 
} 

С насмешливыми рамками, как Mockito поведение этого класса в случае IOException -s легче тестировать сейчас (обратите внимание, что вы можете вернуться издевается, которые бросают исключения с завода). Ниже приведен пример:

@RunWith(MockitoJUnitRunner.class) 
public class MyTest 
{ 
    @Mock 
    private BufferedReaderFactory mockFactroy; 

    @Test 
    public void testIOException() throws IOException 
    { 
     String ivalidFileName = "invalid.txt"; 
     //throw exception in case that invalid file name is passed to the factory 
     Mockito.when(mockFactroy.createBufferedReader(ivalidFileName)).thenThrow(new IOException("Hello!")); 

     CsvFileReader csvFileReader = new CsvFileReader(mockFactroy); 
     //invoke with a factory that throws exceptions 
     csvFileReader.readCsvFile(ivalidFileName); 
     //... 
     //and make a sensible test here, e.g. check that empty list is returned, or proper message is logged, etc. 
    } 
} 

Вы можете сделать это без Mockito, конечно, путем внедрения испытательной фабрики. Но это более громоздко, особенно в более сложных случаях использования. После того, как будет выброшен IOException, вы получите соответствующий отчет о закрытии от JaCoCo.

Также обратите внимание на ограничение JaCoCo, упомянутое here, в разделе Исходные коды кода с исключениями не показывают покрытие. Зачем?

2

Учитывая текущую подпись вашего метода при испытании, добираясь до полного охвата нелегко: ваш блок catch выполняется только тогда, когда исключение выбрано в вашем блоке try.

Один из способов решения этой проблемы: не передавать имя файла, а сам объект-читатель. Нравится:

public static List<Student> readCsvFile(String fileName) { 
    return readCsvFile(new BufferedReader(fileName)); 
} 

static List<Student> readCsvFile(BufferedReader reader) { 
    try { 
    ... 
    } catch(... 

Теперь вы можете написать несколько конкретных модульных тестов для этого второго метода. Вы проводите свои тесты, которые просто делают «правильное» чтение; но вы добавляете тот, где вы проходите в издеваемом объекте читателя ... который просто бросает исключение в какой-то момент. Обратите внимание, что я сделал этот новый метод только защищенным пакетом - вы, вероятно, не хотите использовать этот «общедоступный»; и сделать его частным, будет препятствовать его тестированию на единицу.

Это должно помочь вам достичь полного охвата. Конечно, вам также понадобится хотя бы один тест, чтобы «покрыть» метод ввода строк.

Некоторые примечания:

  1. Будьте осторожны заново изобретать колесо. Уже существует множество существующих синтаксических анализаторов CSV. И будьте уверены: написание правильно CSV-анализатор, который способен справляться со всеми «правильными» входами CSV, намного сложнее, чем кажется. Если это не для «учебных целей», я настоятельно рекомендую не написать собственный анализатор CSV.
  2. Будьте осторожны при изготовлении таких вещей Статические. Как сказал, настоящий синтаксический анализатор CSV - это сложная вещь, и он стоит своего собственного класса. Таким образом, никакие статические вспомогательные методы - обычный класс, который вы создаете для того, чтобы затем называть методы на нем (что также для использования зависимой инъекции, которая помогла бы с проблемой, о которой вы спрашиваете ... получение исключений, брошенных внутри блоков try)
  3. Вы ловите Исключение в вашем примере кода. Не делайте этого - попытайтесь поймать те исключения, которые ваш код действительно может произвести (вероятно, IOException в вашем случае).
Смежные вопросы