junit 验证日志输出
在本文中,我将快速向您展示如果您需要解决以下挑战,那么JUnit规则有多方便
一个方法可以捕获异常,并且必须在抛出或引发包装异常之前执行一些额外的任务。
调用额外任务和引发的异常应通过单元测试进行验证。
这意味着你有一些这样的代码
public class MyThrowingClass {
private final ExceptionProcessor exceptionProcessor;
public MyThrowingClass(ExceptionProcessor exceptionProcessor) {
this.exceptionProcessor = exceptionProcessor;
}
public void runTask() throws NullPointerException {
try {
// something to do here
throw new NullPointerException("It's null Jim");
} catch (NullPointerException e) {
exceptionProcessor.process(e); // This call needs to be verified
throw e;
}
}
}
并在这行中调用
exceptionProcessor.process(e);
需要进行验证以及引发异常。
直截了当……但丑陋
我不会详细介绍此变体
try {
cut.runMyMethod();
} catch(Exception e) {
verify(...);
assertThat(e).isInstanceOf();
}
因为我个人尽量避免在测试代码中尝试使用catch结构。
容易的第一
验证引发异常非常容易,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;
@Override
public 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;
}
@Override
public void evaluate() throws Throwable {
nextStatement.evaluate();
verifyRuleCallback.execute();
}
}
}
如您所见,它实现了TestRule接口,并提供了一种设置VerifyRuleCallback的方法。 然后在需要执行以运行我们自己的回调评估的VerifyRuleStatement的评估方法中使用该回调。
绑在一起
使用新规则和回调,测试可能看起来像这样
public class MyThrowingClassShould {
@Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
@InjectMocks
MyThrowingClass cut;
@Mock
ExceptionProcessor processor;
@Rule
public ExpectedException exception = ExpectedException.none();
@Rule
public 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
junit 验证日志输出