如何测试使用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);
}
请注意,try
.. catch
后面需要assertTrue
。
答案 0 :(得分:11)
测试不快乐的路径可能很难。这是我用黄瓜做的一种很好的方式。
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()));
}
这种方法最有价值的是,当你不期待它时,它不会吞下一个例外。
答案 1 :(得分:7)
您是否尝试过使用带有ExpectedException的junit @Rule注释,如下所示:
@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);
}
答案 2 :(得分:5)
行为测试验证您的项目是否遵循规范,我怀疑用户在使用系统时是否期望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();
}
答案 3 :(得分:3)
从未使用过Cucumber,但会
public void null_exception_thrown() {
try {
taskCreater.createTask(null);
fail("Null Pointer Expected");
} catch (NullPointerException e) {
// Do Nothing
}
}
为你工作?
答案 4 :(得分:1)
我认为Cucumber的目的是测试更高级别的验收测试而不是低级单元测试,因为我们将测试与行为相反的结构,这不是黄瓜框架的理想用法
答案 5 :(得分:1)
我建议您使用 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);
}
答案 6 :(得分: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());
}
完整的项目可以在这里看到:Steps for cucumber