Cucumber 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);
}

Обратите внимание на необходимость _3 _.._ 4_, за которым следует assertTrue на флаге.


person samach    schedule 24.06.2013    source источник
comment
Лично я не уверен, что вы должны (почти) когда-либо получать исключения в проходящем тестовом примере. Cucumber написан с точки зрения точки зрения пользователя, и пользователь никогда не должен знать, что возникло исключение - программа должна каким-то образом решать проблему, отображая какое-то сообщение, говорящее пользователю, что он не должен делать то, что только что попробовал. делать или что-то в этом роде.   -  person Dylanthepiguy    schedule 30.12.2016


Ответы (7)


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

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

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

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

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()));
}

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

person Niel de Wet    schedule 03.04.2014
comment
Мне нравится этот подход, я думаю, что эту строку } catch (RuntimeException e) { можно заменить на } catch (YourExpectedException e) {, поэтому, если возникнет исключение, которого вы не ожидаете, тест завершится ошибкой. - person Olivier Boissé; 12.01.2017

Вы пробовали использовать аннотацию 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);
}
person Chung Nguyen    schedule 27.06.2013
comment
Это действительно работает? В соответствии с этим это не имеет никакого эффекта: github.com/cucumber/cucumber-jvm/issues/393 - person bcoughlan; 09.02.2016

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

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

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

например:

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 */

В моем модульном тесте у меня было бы:

@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();
}
person Tarek    schedule 11.09.2013
comment
«Пользователь» не обязательно является человеком. Интерфейс ввода, с которым работают тесты, может быть API. - person bcoughlan; 09.02.2016

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

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

                // Do Nothing
             }
        }

работать на вас?

person DaveH    schedule 24.06.2013

Я предлагаю вам использовать org.assertj.assertj-core < / сильный>.

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

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

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

person Vishal Aggarwal    schedule 26.11.2015

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

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

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());
}

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

person Shantonu    schedule 09.07.2018