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

Это уродливо!

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

 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 exceptions = new ArrayList<>(); public void expectException() { expectException = true; } public void add(RuntimeException e) { if (!expectException) { throw e; } exceptions.add(e); } public List 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())); } 

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

Вы пытались использовать аннотацию 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); } 

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

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

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

Тестирование поведения проверяет, соответствует ли ваш проект спецификациям, и я сомневаюсь, что пользователь ожидает исключение 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 */ 

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

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

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

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

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

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

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

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

 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 

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

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

поэтому в определении шага, где i делит на ноль

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

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