Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cucumber JVM: Test if the correct exception is thrown

Tags:

cucumber-jvm

How to test that the correct exception is thrown when using Cucumber JVM? When using JUnit, I would do something like this:

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

As you can see, this is very elegant. But how can I achieve the same elegance, when using cucumber JVM? My test looks like this right now:

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

Note the need for a try..catch followed by an assertTrue on a flag.

like image 707
samach Avatar asked Jun 24 '13 09:06

samach


People also ask

Can we use assert in Cucumber?

Cucumber does not come with an assertion library. Instead, use the assertion methods from a unit testing tool.


2 Answers

Testing the not-happy-path can be hard. Here's a nice way that I've found to do it with cucumber.

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

OK, don't shoot me because I put the Then before the When, I just think it reads better but you don't have to do that.

I store my excepions in a (cucumber-scoped) world object, but you could also do it in your step file, but this will limit you later.

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

Your steps are then pretty simple:

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

In a step where you are (at least sometimes) expecting an exception, catch it and add it to the world.

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

Now you can check whether the exception was recorded in the world.

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

The most valuable thing about this approach is that it won't swallow an exception when you don't expect it.

like image 112
Niel de Wet Avatar answered Oct 21 '22 02:10

Niel de Wet


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);
}
like image 7
Chung Nguyen Avatar answered Oct 21 '22 01:10

Chung Nguyen