Cuvumber JVM: проверьте, выбрасывается ли правильное исключение

Как проверить, что выдается правильное исключение при использовании Cucumber JVM? При использовании JUnit я бы сделал что-то вроде этого:

@Test(expected = NullPointerException.class)
public void testExceptionThrown(){
    taskCreater.createTask(null);
}

Как видите, это очень элегантно. Но как мне добиться такой же элегантности при использовании огурца JVM? Мой тест выглядит следующим образом:

@Then("the user gets a Null pointer exception$")
public void null_exception_thrown() {
    boolean result = false;
    try {
        taskCreater.createTask(null);
    } catch (NullPointerException e) {
        result = true;
    }
    assertTrue(result);
}

Обратите внимание на необходимость try.. catch последующим assertTrue для флага.

Ответ 1

Тестирование не-счастливого пути может быть трудным. Здесь хороший способ, который я нашел, чтобы сделать это с огурцом.

Scenario: Doing something illegal should land you in jail
    Then a failure is expected
    When you attempt something illegal
    And it fails.

Хорошо, не стреляйте в меня, потому что я помещал Then перед When, я просто думаю, что он читается лучше, но вам не нужно это делать.

Я храню свои исключения в объекте world (cucumber-scoped), но вы также можете сделать это в своем файле шагов, но это ограничит вас позже.

public class MyWorld {
    private boolean expectException;
    private List<RuntimeException> exceptions = new ArrayList<>();

    public void expectException() {
        expectException = true;
    }

    public void add(RuntimeException e) {
        if (!expectException) {
            throw e;
        }
        exceptions.add(e);
    }

    public List<RuntimeException> getExceptions() {
        return exceptions;
    }
}

Ваши шаги довольно просты:

@Then("a failure is expected")
public void a_failure_is_expected() {
    myWorld.expectException();
}

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

@When("you attempt something illegal")
public void you_attempt_something_illegal() {
    try {
        myService.doSomethingBad();
    } catch (RuntimeException e) {
        world.add(e);
    }
}

Теперь вы можете проверить, было ли исключение записано в мире.

@And("it fails")
public void it_fails() {
    assertThat(world.getExceptions(), is(not(empty()));
}

Самое ценное в этом подходе - это то, что он не проглотит исключение, если вы этого не ожидаете.

Ответ 2

Вы пытались использовать аннотацию junit @Rule с ExpectedException, например:

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

@Then("the user gets a Null pointer exception$")
public void null_exception_thrown() {
    expectedEx.expect(NullPointerException.class);
    //expectedEx.expectMessage("the message");
    taskCreater.createTask(null);
}

Ответ 3

Тестирование поведения проверяет, соответствует ли ваш проект спецификациям, и я сомневаюсь, что пользователь ожидает исключение NullPointerException при использовании системы.

По моему мнению (я не знаком с вашим проектом), исключения следует проверять только во время тестов Unit, так как они соответствуют непредвиденной ошибке или ошибке пользователя.

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

например:

test.feature

Given that I have a file "users.txt"
And I try to import users /* If an Exception is thrown here, the test fails */
Then I should see the following users: /* list of users */

В моем unit test я бы:

@Test(expected = MyException.class)
public void importUsersShouldThrowMyExceptionWhenTheFileIsNotFound() {
    // mock a call to a file and throw an exception
    Mockito.when(reader.readFile("file.txt").thenThrow(new FileNotFoundException());

    importer.importUsers();
}

Ответ 4

Никогда не использовался огурец, но

    public void null_exception_thrown() {
            try {
                  taskCreater.createTask(null);
                  fail("Null Pointer Expected");
            } catch (NullPointerException e) {

                // Do Nothing
             }
        }

работает для вас?

Ответ 5

Я считаю, что Cucumber предназначен для тестирования приемочных тестов более высокого уровня, чем модульные тесты нижнего уровня, так как в этом случае мы будем тестировать структуру, противоположную поведению, которая не является желательным использованием рамок Cucumber.

Ответ 6

Я предлагаю вам использовать org.assertj.assertj-core.

Благодаря классу Утверждения вы можете упростить свое утверждение, как показано ниже:

@Then("the user gets a Null pointer exception$")
public void null_exception_thrown() {
    Assertions.assertThatThrownBy(() -> taskCreater.createTask(null)).
               isInstanceOf(NullPointerException.class);
}

Ответ 7

Раньше я ожидал имя исключения в пошаговых функциях. для примера теста калькулятора

Вот моя запись файла функций для исключения деления:

Scenario: Dividing a number with ZERO
Given I want to test calculator
When I insert 5.5 and 0.0 for division
Then I got Exception ArithmeticException

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

Теперь нам нужно получить исключение при делении на ноль и вставить переменную. И получите эту переменную, чтобы сравнить ее имя класса (имя исключения)

Итак, в определении шага, где я делю на ноль

private Exception actualException;
 @When("^I insert (.+) and (.+)for division$")
public void iInsertAndForDivision(double arg0, double arg1) throws Throwable {
    try {
        result = calculator.div(arg0, arg1);
    } catch (Exception e) {
        actualException =e;
    }
}

И мне нужно определение шага для проверки исключения

  @Then("^I got Exception (.+)")
public void iGotArithmeticException(String aException) throws Throwable {        
Assert.assertEquals("Exception MissMatch",aException,actualException.getClass().getSimpleName());
}

Полный проект можно увидеть здесь: Шаги для огурца