2013-06-24 94 views
10

我有点惊讶,我无法在线找到这个问题的答案。 不管怎么说使用JUnit时,用于测试是否正确抛出异常,我会做这样的事情:黄瓜JVM:测试是否抛出正确的异常

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

这是丑陋的!

+0

正确缩进。 – Infested

+1

就个人而言,我不确定你应该(几乎)在通过测试用例中得到例外。黄瓜是根据用户的观点编写的,用户不应该知道抛出异常 - 程序应该以某种方式处理问题,通过显示一些排序消息告诉用户他们不应该做他们刚刚尝试过的东西要做,或者类似的事情。 – Dylanthepiguy

回答

3

没有用过黄瓜,但会

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

       // Do Nothing 
      } 
     } 

为你工作?

7

您是否尝试过使用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); 
} 
+0

这是正确的方法。 –

+2

这真的有用吗?据此它没有效果:https://github.com/cucumber/cucumber-jvm/issues/393 – bcoughlan

+0

它似乎在黄瓜忽略junit规则 –

2

行为测试,如果你的项目如下规格验证,我怀疑,同时使用该系统的用户需要一个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(); 
} 
+0

'用户'不一定是人类。测试使用的输入接口可能是一个API。 – bcoughlan

10

测试的不快乐路径能吃苦耐劳。这是我发现用黄瓜做的一个很好的方法。

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

OK,不要拍我,因为我把ThenWhen之前,我只是觉得它读取更好,但你没有这样做。

我将我的excepions存储在一个(黄瓜作用域)的世界对象中,但您也可以在您的步骤文件中执行此操作,但这会稍后限制您的工作。

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

这种方法最有价值的是,它不会吞下异常,当你不期望它。

+3

我喜欢这种方式,我认为这行''catch(RuntimeException e){'可以被替换'} catch(YourExpectedException e){'所以如果你不期望的异常被抛出,测试将会失败 –

0

相信黄瓜是指测试低于电平单元测试更高水平的验收测试如在这种情况下我们将测试相对的行为这不是黄瓜框架的期望使用的结构。

0

我建议你使用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); 
}