В fail()
библиотеке JUnit4 есть метод. Мне это нравится, но испытываю нехваткуpass()
метода, которого нет в библиотеке. Почему это так?
Я обнаружил, что могу использовать assertTrue(true)
вместо этого, но все равно выглядит нелогично.
@Test
public void testSetterForeignWord(){
try {
card.setForeignWord("");
fail();
} catch (IncorrectArgumentForSetter ex){
}
// assertTrue(true);
}
pass
метода.Ответы:
Пока тест не генерирует исключение, он проходит, если в вашей
@Test
аннотации не указано ожидаемое исключение. Я полагаю, что apass()
может вызвать специальное исключение, которое JUnit всегда интерпретирует как прохождение, чтобы сократить тест, но это будет противоречить обычному дизайну тестов (т.е. предположить успех и только потерпеть неудачу, если утверждение не выполняется) и, если люди получили идея, которую было бы предпочтительнее использоватьpass()
, значительно замедлила бы прохождение большого набора тестов (из-за накладных расходов на создание исключений). Неудачные тесты не должны быть нормой, поэтому нет ничего страшного, если у них есть такие накладные расходы.Обратите внимание, что ваш пример можно переписать так:
@Test(expected=IncorrectArgumentForSetter.class) public void testSetterForeignWord("") throws Exception { card.setForeignWord(""); }
Кроме того, вы должны отдавать предпочтение использованию стандартных исключений Java. Вы
IncorrectArgumentForSetter
должны , вероятно , бытьIllegalArgumentException
.источник
pass()
метод не может просто ничего не делать, иначе тест может не сработать после его вызова. Я удалил это предложение.Вызовите
return
оператор в любое время, когда ваш тест будет завершен и пройден.источник
Я думаю, что на этот вопрос нужен обновленный ответ, поскольку большинство ответов здесь довольно устарели.
Во-первых, на вопрос OP:
Я думаю, что довольно хорошо принято, что введение концепции «ожидаемого исключения» в JUnit было плохим ходом, поскольку это исключение могло возникнуть где угодно, и оно пройдет проверку. Это работает, если вы генерируете (и утверждаете) очень специфичные для домена исключения, но я выбрасываю только такие исключения, когда я работаю над кодом, который должен быть абсолютно безупречным, - большинство APIS просто выбрасывает встроенные исключения, такие как
IllegalArgumentException
илиIllegalStateException
. Если два ваших вызова могут потенциально вызвать эти исключения, тогда@ExpectedException
аннотация будет зеленой полосой для вашего теста, даже если это неправильная строка, которая вызывает исключение!Для этой ситуации я написал класс, который, я уверен, многие здесь написали, это
assertThrows
метод:public class Exceptions { private Exceptions(){} public static void assertThrows(Class<? extends Exception> expectedException, Runnable actionThatShouldThrow){ try{ actionThatShouldThrow.run(); fail("expected action to throw " + expectedException.getSimpleName() + " but it did not."); } catch(Exception e){ if ( ! expectedException.isInstance(e)) { throw e; } } } }
этот метод просто возвращает, если возникает исключение, что позволяет вам выполнять дальнейшие утверждения / проверки в вашем тесте.
с синтаксисом java 8 ваш тест выглядит действительно красиво. Ниже приведен один из самых простых тестов нашей модели, в котором используется этот метод:
@Test public void when_input_lower_bound_is_greater_than_upper_bound_axis_should_throw_illegal_arg() { //setup AxisRange range = new AxisRange(0,100); //act Runnable act = () -> range.setLowerBound(200); //assert assertThrows(IllegalArgumentException.class, act); }
эти тесты немного неудобны, потому что шаг «действие» на самом деле не выполняет никаких действий, но я думаю, что смысл все еще довольно ясен.
в maven также есть крошечная библиотека, называемая catch-exception, которая использует синтаксис в стиле mockito для проверки того, что исключения генерируются. Выглядит симпатично, но я не фанат динамических прокси. Тем не менее, синтаксис настолько хорош, что остается заманчивым:
// given: an empty list List myList = new ArrayList(); // when: we try to get the first element of the list // then: catch the exception if any is thrown catchException(myList).get(1); // then: we expect an IndexOutOfBoundsException assert caughtException() instanceof IndexOutOfBoundsException;
Наконец, для ситуации, с которой я столкнулся, чтобы добраться до этой темы, есть способ игнорировать тесты, если выполняется какое-то условие.
Прямо сейчас я работаю над вызовом некоторых DLL через библиотеку загрузки собственной библиотеки Java под названием JNA, но наш сервер сборки находится в ubuntu. Мне нравится управлять такого рода разработками с помощью тестов JUnit - даже если они на данный момент далеки от «единиц» -. Что я хочу сделать, так это запустить тест, если я нахожусь на локальной машине, но игнорировать тест, если мы на ubuntu. В JUnit 4 есть для этого положение, которое называется
Assume
:@Test public void when_asking_JNA_to_load_a_dll() throws URISyntaxException { //this line will cause the test to be branded as "ignored" when "isCircleCI" //(the machine running ubuntu is running this test) is true. Assume.assumeFalse(BootstrappingUtilities.isCircleCI()); //an ignored test will typically result in some qualifier being put on the results, //but will also not typically prevent a green-ton most platforms. //setup URL url = DLLTestFixture.class.getResource("USERDLL.dll"); String path = url.toURI().getPath(); path = path.substring(0, path.lastIndexOf("/")); //act NativeLibrary.addSearchPath("USERDLL", path); Object dll = Native.loadLibrary("USERDLL", NativeCallbacks.EmptyInterface.class); //assert assertThat(dll).isNotNull(); }
источник
Я также искал
pass
метод для JUnit, чтобы я мог сократить некоторые тесты, которые не были применимы в некоторых сценариях (есть интеграционные тесты, а не чистые модульные тесты). Так что жаль, что его там нет.К счастью, есть способ условно игнорировать тест, который в моем случае подходит даже лучше, используя
assumeTrue
метод:Таким образом, здесь тест будет выполняться, только если isTestApplicable истинно, иначе тест будет проигнорирован.
источник
В методе передачи нет необходимости, потому что, когда из тестового кода не выбрасывается AssertionFailedException, модульный тестовый пример будет пройден.
Метод fail () фактически генерирует исключение AssertionFailedException, чтобы не выполнить testCase, если в этот момент доходит управление.
источник
Я думаю, что этот вопрос - результат небольшого непонимания процесса выполнения теста. В JUnit (и других инструментах тестирования) результаты подсчитываются для каждого метода, а не для каждого вызова assert. Нет счетчика, который отслеживает, сколько прошло / не
assertX
удалось выполнить.JUnit выполняет каждый тестовый метод отдельно. Если метод завершился успешно, значит тест зарегистрирован как «пройден». Если возникает исключение, то тест регистрируется как «не пройденный». В последнем случае возможны два подслучая: 1) исключение утверждения JUnit, 2) исключения любого другого типа. В первом случае статус будет «сбой», а во втором - «ошибка».
В
Assert
классе доступно множество сокращенных методов для выдачи исключений утверждений. Другими словами,Assert
это уровень абстракции над исключениями JUnit.Например, это исходный код
assertEquals
на GitHub :/** * Asserts that two Strings are equal. */ static public void assertEquals(String message, String expected, String actual) { if (expected == null && actual == null) { return; } if (expected != null && expected.equals(actual)) { return; } String cleanMessage = message == null ? "" : message; throw new ComparisonFailure(cleanMessage, expected, actual); }
Как видите, в случае равенства ничего не происходит, иначе будет выброшено исключение.
Так:
assertEqual("Oh!", "Some string", "Another string!");
просто генерирует
ComparisonFailure
исключение, которое будет перехвачено JUnit, иassertEqual("Oh?", "Same string", "Same string");
ничего не делает.
В общем, что-то вроде
pass()
бы не имело никакого смысла, потому что ничего не делало.источник