JUnit4 fail() здесь, но где pass()?
В библиотеке JUnit4 существует метод fail()
. Мне это нравится, но испытывает недостаток метода pass()
, который отсутствует в библиотеке. Почему это так?
Я узнал, что я могу использовать assertTrue(true)
вместо этого, но все равно выглядит нелогичным.
@Test
public void testSetterForeignWord(){
try {
card.setForeignWord("");
fail();
} catch (IncorrectArgumentForSetter ex){
}
// assertTrue(true);
}
Ответы
Ответ 1
Пока тест не генерирует исключение, он проходит, если только аннотация @Test
не указывает ожидаемое исключение. Я полагаю, что pass()
может вызвать особое исключение, которое JUnit всегда интерпретирует как передачу, чтобы коротко закоротить тест, но это будет противоречить обычному дизайну тестов (т.е. Предполагать успех и только терпеть неудачу, если утверждение терпит неудачу) если люди поняли, что предпочтительнее использовать pass()
, это значительно замедлит большой набор тестов (из-за накладных расходов на создание исключений). Неудачные испытания не должны быть нормой, поэтому это не имеет большого значения, если у них есть накладные расходы.
Обратите внимание, что ваш пример можно переписать следующим образом:
@Test(expected=IncorrectArgumentForSetter.class)
public void testSetterForeignWord("") throws Exception {
card.setForeignWord("");
}
Кроме того, вы должны одобрить использование стандартных исключений Java. Вероятно, ваш IncorrectArgumentForSetter
должен быть IllegalArgumentException
.
Ответ 2
Вызов return
оператора в любое время, когда ваш тест завершен и передан.
Ответ 3
Я думаю, что этот вопрос нуждается в обновленном ответе, так как большинство ответов здесь довольно устарели.
Во-первых, вопрос OP:
Я думаю, что он довольно хорошо согласился с тем, что введение концепции ожидаемого excepetion в 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);
}
эти тесты немного заурядны, потому что шаг "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();
}
Ответ 4
Я искал метод pass
для JUnit, чтобы я мог закоротить некоторые тесты, которые не были применимы в некоторых сценариях (есть тесты интеграции, а не чистые модульные тесты). Так плохо, что его там нет.
К счастью, есть способ условно проигнорировать тест, который в действительности подходит для моего случая, используя метод assumeTrue
:
Assume.assumeTrue(isTestApplicable);
Итак, здесь тест будет выполнен, только если isTestApplicable истинно, иначе тест будет проигнорирован.
Ответ 5
Нет необходимости в методе pass, потому что если из тестового кода не выдается исключение AssertionFailedException, произойдет событие unit test.
Метод fail() на самом деле вызывает исключение AssertionFailedException, чтобы сбой в testCase, если элемент управления приходит к этой точке.
Ответ 6
Я думаю, что этот вопрос является результатом небольшого непонимания процесса выполнения теста. В JUnit (и других инструментах тестирования) результаты подсчитываются по методу, а не по запросу. Нет счетчика, который отслеживает, сколько пропущенных/неудачных 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()
не имело бы никакого смысла, потому что ничего не делало.
Ответ 7
Все проходит, и испытания должны пройти...