Как проверить, если несколько строк кода выдают исключение в junit4 Java - PullRequest
0 голосов
/ 29 апреля 2018

Я пишу отрицательный тест для метода add(T elem, int index) класса. Ожидается, что метод выдаст IllegalArgumentException, если index < 0 || index > size || elem == null. Мой тест выглядит так:

@Rule
public ExpectedException thrown = ExpectedException.none();

@Test(expected = IllegalArgumentException.class) 
public void addNegTest() {
    l0.add(42, 10);  // index > size 
    l0.add(42, -1);  // index < 0
    l0.add(null, 2); // elem == null
}

Тест становится зеленым, но я понял, что требуется всего 1 из этих 3 строк кода, чтобы вызвать исключение, чтобы тест стал зеленым. Поэтому, если я добавлю 1 строку в код, как этот, тест все равно станет зеленым.

@Test(expected = IllegalArgumentException.class) 
public void addNegTest() {
    l0.add(42, 10);  // index > size 
    l0.add(42, -1);  // index < 0
    l0.add(null, 2); // elem == null
    l0.add(42, 0);   // this is perfectly fine 
}

Так как же я могу убедиться, что тест проверяет, если каждая строка выдает исключение, а не только одно?

Ответы [ 3 ]

0 голосов
/ 29 апреля 2018

Путем написания четырех разных методов испытаний:

@Test(expected = IllegalArgumentException.class) 
public void addNegTest_indexTooLarge() {
    l0.add(42, 10);  // index > size 
}

@Test(expected = IllegalArgumentException.class) 
public void addNegTest_negativeIndex() {
    l0.add(42, -1);  // index < 0
}

@Test(expected = IllegalArgumentException.class) 
public void addNegTest_nullElement() {
    l0.add(null, 2); // elem == null
}

@Test
public void addNegTest_ok() {
    l0.add(42, 0);   // this is perfectly fine 
}

Если вы используете плагин, такой как JaCoCo , вы можете визуально подтвердить, что все возможные пути покрыты.

0 голосов
/ 29 апреля 2018

Исключение прервет метод, который выполняется в данный момент, до тех пор, пока исключение не будет перехвачено. Таким образом, у вас есть две возможности:

Один метод для каждого теста

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

@Test(expected = IllegalArgumentException.class) 
public void addIndexGreaterThanSize() {
    l0.add(42, 10);  // index > size 
}

@Test(expected = IllegalArgumentException.class) 
public void addIndexNegative() {
    l0.add(42, -1);  // index < 0
}

@Test(expected = IllegalArgumentException.class) 
public void addElementNull() {
    l0.add(null, 2); // elem == null
}

Лови исключения самостоятельно

Вы также можете перехватить все исключения самостоятельно и не пройти тест, если исключение не выдается. При использовании этого метода вы можете проверить дополнительные свойства исключения (например, сообщение).

@Test
public void addNegTest() {
    try {
        l0.add(42, 10);  // index > size 
        fail();
    } catch (IllegalArgumentException e) {}
    try {
        l0.add(42, -1);  // index < 0
        fail();
    } catch (IllegalArgumentException e) {}
    try {
        l0.add(null, 2); // elem == null
        fail();
    } catch (IllegalArgumentException e) {}
}

Если вы хотите проверить дополнительные свойства сгенерированного исключения, вы можете выбрать второй метод. В противном случае, я рекомендую первый вариант, так как он проще для понимания и меньше кода для написания самостоятельно.

0 голосов
/ 29 апреля 2018

Ожидаемое исключение ожидается в области выполнения тестового метода whole независимо от того, не выполняются ли другие операторы.
Поэтому вы должны создать метод тестирования по возможному сценарию.

@Test(expected = IllegalArgumentException.class) 
public void add_with_index_greater_than_size() {
    l0.add(42, 10);  // index > size 
}  

@Test(expected = IllegalArgumentException.class) 
public void add_with_index_less_than_zero() {
    l0.add(42, -1);  
}  

@Test(expected = IllegalArgumentException.class) 
public void add_with_null_arg() {
    l0.add(null, 10); 
}  

@Test
public void add() {
    l0.add(42, 10);  
    Assert.assertEquals(42, l0.get(10));
}  

Несмотря на то, что вы все еще можете использовать один метод тестирования с таким количеством try/catch операторов, как и сценарии с ошибками для тестирования, как показано в ответ SilverNak , я бы не рекомендовал его для удобства чтения.

Обратите внимание, что помимо вашего случая указание каждого отдельного сценария в своем собственном методе является хорошей практикой, поскольку делает тесты более читабельными, а также упрощает / облегчает исправление теста, который не пройден, поскольку его ответственность яснее и четко определена.


JUnit 5 улучшений

Обратите внимание, что в последней версии JUnit вы можете собирать некоторые распространенные случаи одним и тем же способом, не уменьшая читабельность кода.
Вы можете собрать недопустимые случаи с неверным индексом, таким как:

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
...
@Test
public void add_with_index_less_than_zero_or_greater_than_size() {
    Assertions.assertThrows(IllegalArgumentException.class, 
                             () -> l0.add(42, 10));
    Assertions.assertThrows(IllegalArgumentException.class, 
                             () -> l0.add(42, -1));
}  

Но я бы оставил это в отдельном методе:

import  org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
...
@Test
public void add_with_null_arg() {
    Assertions.assertThrows(IllegalArgumentException.class, 
                             () -> l0.add(null, 10));
}  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...