22

使用 Cucumber JVM 时如何测试是否抛出了正确的异常?使用 JUnit 时,我会这样做:

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

如您所见,这是非常优雅的。但是,当使用 cucumber 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后跟一个assertTrueon 标志。

4

7 回答 7

13

测试不愉快的路径可能很困难。这是我发现用黄瓜做的一个好方法。

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

这种方法最有价值的地方在于,它不会在您没有预料到的时候吞下异常。

于 2014-04-03T15:47:12.493 回答
7

Have you tried using the junit @Rule annotation with ExpectedException, like this:

@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);
}
于 2013-06-27T00:56:05.187 回答
5

行为测试验证您的项目是否遵循规范,我怀疑用户在使用系统时期望 NullPointerException。

在我看来(我不熟悉您的项目),异常应该只在单元测试期间检查,因为它们对应于意外错误或用户错误。

在行为测试期间检查异常是非常不寻常的。如果在测试期间抛出异常,它应该会失败。

例如:

测试功能

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();
}
于 2013-09-11T20:15:46.707 回答
3

从来没有用过黄瓜,但会

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

                // Do Nothing
             }
        }

为你工作?

于 2013-06-24T09:41:45.443 回答
3

我建议你使用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);
}
于 2017-11-18T17:43:32.713 回答
1

我相信 Cucumber 旨在测试更高级别的验收测试而不是较低级别的单元测试,因为在这种情况下,我们将测试与行为相反的结构, 这不是 Cucumber 框架的预期用途。

于 2015-11-26T03:38:12.253 回答
1

我曾经在功能步骤中有预期的异常名称。对于计算器测试示例

这是我的除法异常功能文件条目:

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

完整的项目可以在这里看到:黄瓜的步骤

于 2018-07-09T02:09:03.740 回答