Подтвердить что ты не робот

Тест JUnit - анализ ожидаемых исключений

В JUnit в настоящее время я использую аннотацию, чтобы ожидать исключения в моих тестах.

Есть ли способ проанализировать это исключение? Например, я ожидаю CriticalServerException, но я также хочу проверить содержимое метода getMessage.

4b9b3361

Ответ 1

Если у вас JUnit 4.7 или выше, попробуйте ExpectedException

В этом вопросе есть пример, который скопирован ниже:

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

@Test
public void testRodneCisloRok(){
    exception.expect(IllegalArgumentException.class);
    exception.expectMessage("error1");
    new RodneCislo("891415",dopocitej("891415"));
}

Ответ 2

Я не уверен, что вам нужно. Использование блока try-catch для проверки сообщения об ошибке так junit3ish. У нас есть эта замечательная функция, теперь вы можете написать @Test(expected=CriticalServerException.class), и вы хотите вернуться назад и снова использовать try-catch для получения ожидаемого исключения, просто для проверки сообщения об ошибке?

IMO, вы должны остаться для аннотации @Test(expected=CriticalServerException.class) и проигнорировать сообщение об ошибке. Проверка сообщения об ошибке, которое может быть изменено много, поскольку это более "понятная для человека" строка, а не техническое значение, также может быть сложной задачей. Вы заставляете исключение иметь определенное сообщение об ошибке, но вы не знаете, кто создал исключение и какое сообщение об ошибке он выбрал.

В общем, вы хотите проверить, выбрал ли метод исключение или нет, а не то, что похоже на фактическое сообщение об ошибке. Если сообщение об ошибке действительно так важно, вы можете подумать об использовании подкласса исключения, которое оно выбрасывает, и проверить его в @Test(expected=...).

Ответ 3

try{ 
    //your code expecting to throw an exception
    fail("Failed to assert :No exception thrown");
} catch(CriticalServerException ex){
    assertNotNull("Failed to assert", ex.getMessage()) 
    assertEquals("Failed to assert", "Expected Message", ex.getMessage());
}

Ответ 4

try
{
    // your code

    fail("Didn't throw expected exception");
}
catch(CriticalServerException e)
{
    assertEquals("Expected message", e.getMessage());
}

Ответ 5

try {
    // test code invacation
    fail("Exception not throw!!!");
} catch(CriticalServerException ex) {
    assertTrue("Invalid exception data", ex.toString().contains("error text"));
}

Ответ 6

Используйте MethodRule как общее решение, если у вас есть много тестовых примеров для тестирования

public class ExceptionRule implements MethodRule {
    @Override
    public Statement apply(final Statement base, final FrameworkMethod method, Object target) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                try {
                    base.evaluate();
                    Assert.fail();
                } catch (CriticalServerException e) {
                    //Analyze the exception here
                }
            }
        };    
    }
}

Затем используйте правило для вашего тестового класса:

@Rule public ExceptionRule rule = new ExceptionRule(); 

Ответ 7

Я не думаю, что есть способ сделать это, используя аннотацию. Возможно, вам придется вернуться к методу try-catch, где в блоке catch вы можете проверить сообщение

Ответ 8

Используйте catch-exception:

catchException(obj).doSomethingCritical();
assertTrue(caughtException() instanceof CriticalServerException);
assertEquals("Expected Message", caughtException().getMessage());

Ответ 9

Посмотрите fluent-exception-rule, он "объединяет правила Junit ExpectedException и AssertJ assertions".

import pl.wkr.fluentrule.api.FluentExpectedException;
...
@Rule
public FluentExpectedException thrown = FluentExpectedException.none();

@Test
public void testDoSomethingCritical() {
    thrown.expect(CriticalServerException.class).hasMessage("Expected Message").hasNoCause();
    obj.doSomethingCritical();
}

Ответ 10

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

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

    expectedException.expect(IllegalArgumentException.class);
    expectedException.expectMessage("Parameter is not valid"); //check string contains
    expectedException.expectMessage(CoreMatchers.equalTo("Parameter is not valid")); //check string equals

Примечание. Это будет работать для junit 4.9.

Ответ 11

Решение Java 8

Вот служебная функция, которую я написал:

public final <T extends Throwable> T expectException( Class<T> exceptionClass, Runnable runnable )
{
    try
    {
        runnable.run();
    }
    catch( Throwable throwable )
    {
        if( throwable instanceof AssertionError && throwable.getCause() != null )
            throwable = throwable.getCause(); //allows "assert x != null : new IllegalArgumentException();"
        assert exceptionClass.isInstance( throwable ) : throwable; //exception of the wrong kind was thrown.
        assert throwable.getClass() == exceptionClass : throwable; //exception thrown was a subclass, but not the exact class, expected.
        @SuppressWarnings( "unchecked" )
        T result = (T)throwable;
        return result;
    }
    assert false; //expected exception was not thrown.
    return null; //to keep the compiler happy.
}

(взято из моего блога)

Используйте его следующим образом:

@Test
public void testThrows()
{
    RuntimeException e = expectException( RuntimeException.class, () -> 
        {
            throw new RuntimeException( "fail!" );
        } );
    assert e.getMessage().equals( "fail!" );
}

Кроме того, если вы хотите прочитать некоторые причины, по которым вам следует не проверять сообщение об исключении, см. это: https://softwareengineering.stackexchange.com/a/278958/41811