Отсутствие ветвей при использовании assertTrue вместо assertNull
В Java/Junit мне нужно проверить значение null с некоторым объектом. Существуют различные способы проверки состояния, но я использую assertTrue для большинства своих тестов. Когда я проверяю на nulls в assertTrue, EclEmma утверждает, что он тестирует только одну ветвь.
Когда я разрешаю оператор в переменную вручную (например, устанавливая результат в логическое и передавая его в assertTrue), покрытие кода считается завершенным в утверждении, но не в строке инициализации переменной.
Почему это происходит? Связано ли это с дополнительным байтовым кодом, который Java, по-видимому, добавляет, как упоминалось в http://sourceforge.net/apps/trac/eclemma/wiki/FilteringOptions? Любые решения (помимо использования других утверждений assert).
assertTrue:
assertTrue( myObject == null ); //1 of 2 branches
assertTrue:
boolean test = (myObject == null); //1 of 2 branches missing
assertTrue(test); // complete
assertNull:
assertNull( myObject ) //complete;
Ответы
Ответ 1
Для большинства булевых выражений компилятор Java генерирует дополнительные ветки в байтовом коде.
JaCoCo создает "охват веток" на основе сгенерированного байтового кода, а не на основе исходного кода Java, и, следовательно, отображает дополнительную информацию о охвате веток практически для любого булевого выражения, которое вы использовали.
В вашем коде булево выражение, которое вы используете, myObject == null
.
Чтобы вычислить это значение, компилятор Java генерирует код, нажимая два аргумента в стеке, а затем выполняет условный переход, чтобы нажать 1 (true) или 0 (false) в стеке. JaCoCo сообщает об охвате филиалом этого условного перехода.
Таким образом, тот факт, что вы используете myObject == null
, запускает описанное вами поведение.
Как и другие примеры, попробуйте следующее:
boolean t = true;
boolean f = false;
boolean result1 = (t && f) || f; // 3 out of 6 missed.
boolean result2 = !t; // 1 out of 2 missed.
Это может быть полезно, если булево выражение, например, возвращается функцией, которое используется как условие в инструкции if-then-else где-то в другом месте. Хотя в основном это следствие того, как работает компилятор Java, он помогает оценить состояние покрытия (вместо простого охвата веток) исходного кода Java.
Эта функция не слишком хорошо документирована, но вот несколько указателей:
Таким образом, это действительно связано с дополнительным байтовым кодом, но не с конкретными примерами синтетических байтовых компиляторов, для которых предназначены параметры фильтрации.
ПРИМЕЧАНИЕ. Был ли основной РЕДАКТ, поскольку первоначальный ответ был слишком угадан. Спасибо @ira-baxter за хорошее и критичное обсуждение.
Ответ 2
Тот факт, что Эмма относится к условному выражению как "нечто с веткой" для подсчета (ИМХО) покрытия, имеет простое нарушение. Это не условная ветвь.
Мы можем больше спорить об утверждении; если он был определен как "исключение для исключения при утверждении отказа", тогда у него действительно есть условная ветвь; если он определен [как я думаю, я это делаю, я не эксперт по Java), как "прекратить мою программу при отказе от утверждения", то это не действительно ветка. Также неясны вызовы методов; это условные ветки в том смысле, что если вызываемый метод выдает исключение, поток управления не будет продолжать "остальную часть утверждения".
Наш Инструмент Java Test Coverage получает анализ охвата (ответвления) на таких условных "правых".
Ответ 3
Чтобы получить 100% -ный охват кода по логическим методам, выполните следующие
Class RecordService{
public boolean doesRecordExist(String id){
return id!=null;
}
}
//Method inside your mock
@Test
public boolean testDoesRecordExist(){
RecordService recordService = mock(RecordService.class);
when(recordService.doesRecordExists()).thenReturn(
anyString()).thenReturn(null);
}