在本文中,我将快速向您展示如果您需要解决以下挑战,那么JUnit规则有多方便
方法捕获异常并必须执行一些额外的任务,然后再抛出或引发包装异常。
调用额外任务和引发的异常应通过单元测试进行验证。
这意味着您有一些这样的代码
public class MyThrowingClass {private final ExceptionProcessor exceptionProcessor;public MyThrowingClass(ExceptionProcessor exceptionProcessor) {this.exceptionProcessor = exceptionProcessor;}public void runTask() throws NullPointerException {try {// something to do herethrow new NullPointerException("It's null Jim");} catch (NullPointerException e) {exceptionProcessor.process(e); // This call needs to be verifiedthrow e;}}
}
并在这行中
exceptionProcessor.process(e);
需要进行验证以及引发异常。
直截了当…但是丑陋
我不会详细介绍此变体
try {cut.runMyMethod();
} catch(Exception e) {verify(...);assertThat(e).isInstanceOf();
}
因为我个人尽量避免在测试代码中尝试捕获结构。
容易的第一
验证引发异常相当容易,JUnit在此处提供了潜在的选项
- @Test批注的预期参数和
- 一个叫做ExceptionRule的规则
第一个选项看起来像这样
@Test(expected = NullPointerException.class)
public void myTestWithExpectedParameter() throws Exception {// ...
}
第二个像这样
// ...
@Rule
public ExceptionRule exceptionRule = ExceptionRule.none();// ...@Test
public void myTestWithTheExceptionRule() throws Exception {exceptionRule.expect(NullPointerException.class);// ...
}
不,它变得越来越复杂
上述测试要求背后的问题如下
执行被测方法之后,您执行的所有verify(…)步骤将不会执行,因为如果引发并没有捕获到异常,异常将照常停止其余测试方法的执行。
JUnit救援规则
借助JUnit规则,我们即使在引发异常的情况下,也可以轻松地提供一种提供其他验证步骤的方法。
我知道JUnit已经提供了验证程序规则,但是我不会使用它。 该类的缺点是在设置时将验证逻辑刻录到其中。
因此,我们需要一个规则,该规则允许我们为每个测试指定一个额外的验证逻辑,该逻辑将在测试执行后应用。
一般用法如下所示
@Rule
public VerifyRule verifyRule = new VerifyRule();@Mock
ExceptionProcessor exceptionProcessor;@Test()
public void working() throws Exception {verifyRule.setVerifier(() -> verify(exceptionProcessor).process(any()));// ..
}
为了使它运行起来,我们需要做一些事情
- 验证规则
- 可以在验证规则上设置的任何类型的回调接口
让我们从回调接口开始
public interface VerifyRuleCallback {void execute() throws Throwable;
}
如您所见,这里没什么特别的。
现在,让我们专注于VerifyRule
public class VerifyRule implements TestRule {private VerifyRuleCallback verifyRuleCallback;@Overridepublic Statement apply(Statement base, Description description) {return new VerifyRuleStatement(base);}public void setVerifier(VerifyRuleCallback verifyRuleCallback) {this.verifyRuleCallback = verifyRuleCallback;}private class VerifyRuleStatement extends Statement {private final Statement nextStatement;public VerifyRuleStatement(Statement nextStatement) {this.nextStatement = nextStatement;}@Overridepublic void evaluate() throws Throwable {nextStatement.evaluate();verifyRuleCallback.execute();}}
}
如您所见,它实现了TestRule接口,并提供了一种设置VerifyRuleCallback的方法。 然后,在需要执行以运行我们自己的回调评估的VerifyRuleStatement的评估方法中使用该回调。
绑在一起
使用新规则和回调,测试可能看起来像这样
public class MyThrowingClassShould {@Rulepublic MockitoRule mockitoRule = MockitoJUnit.rule();@InjectMocksMyThrowingClass cut;@MockExceptionProcessor processor;@Rulepublic ExpectedException exception = ExpectedException.none();@Rulepublic VerifyRule verifyRule = new VerifyRule();@Test()public void execute_the_exception_processor_and_rethrow_the_exception_when_it_occur() throws Exception {verifyRule.setVerifier(() -> verify(processor).process(any(NullPointerException.class)));exception.expect(NullPointerException.class);cut.runTask();}
}
摘要
正如我们已经看到的那样,JUnit规则不仅在这种情况下,而且还提出了这样的测试要求时,提供了一种非常简洁的方法来创建清晰易懂的测试代码。
的JUnit 2016-09-26
翻译自: https://www.javacodegeeks.com/2016/09/junit-rules-executing-additional-verification-exceptions-thrown.html