junit白盒测试 案例_JUnit通过失败测试案例

本文介绍了一种处理JUnit测试失败的方法,通过使用@Rule和自定义的@ExpectedFailure注解来确保测试用例在预期的断言错误时能通过。这种方法适用于测试代码中包含Assert错误的情况,例如在增强Fest Assertions框架时。作者警告不要滥用@ExpectedFailure,以免掩盖其他重要的测试声明,并提出了未来可能的增强方向。
摘要由CSDN通过智能技术生成

junit白盒测试 案例

为什么要建立一种预期测试失败的机制?

有一段时间,人们会希望并期望JUnit @Test案例失败。 尽管这种情况很少见,但确实发生了。 我需要检测JUnit测试何时失败,然后(如果期望的话)通过而不是失败。 具体情况是我正在测试一段代码,该代码可能会在对象调用内引发Assert错误。 该代码被编写为对流行的新Fest Assertions框架的增强,因此,为了测试功能,人们希望测试用例会故意失败。

一个办法

一种可能的解决方案是将JUnit @Rule提供的功能与注释形式的自定义标记一起使用。

为什么要使用@Rule?

@Rule对象为测试类和每个测试用例提供了类似于AOP的接口。 在运行每个测试用例之前,将重置规则,并且它们以@Around AspectJ建议的方式公开测试用例的工作方式。

必需的代码元素

  • @Rule对象检查每个@Test用例的状态
  • @ExpectedFailure自定义标记注释
  • 测试用例证明代码有效!
  • 如果带注释的测试用例没有失败,则抛出可选的特定异常

注意:工作代码在我的github页面上可用,并且已添加到Maven Central中。 随意分叉项目并提交拉取请求 Maven用法

<dependency>
    <groupId>com.clickconcepts.junit</groupId>
    <artifactId>expected-failure</artifactId>
    <version>0.0.9</version>
</dependency>

用法示例

在此示例中,“ exception”对象是Fest断言增强的ExpectedException(请查看我的下一篇文章以展示此功能)。 预期的异常将产生断言,并且为了测试这些断言,必须将测试用例标记为@ExpectedFailure

public class ExceptionAssertTest {

    @Rule
    public ExpectedException exception = ExpectedException.none();

    @Rule
    public ExpectedTestFailureWatcher watcher = ExpectedTestFailureWatcher.instance();

    @Test
    @ExpectedFailure('The matcher should fail becasue exception is not a SimpleException')
    public void assertSimpleExceptionAssert_exceptionIsOfType() {
        // expected exception will be of type 'SimpleException'
        exception.instanceOf(SimpleException.class);
        // throw something other than SimpleException...expect failure
        throw new RuntimeException('this is an exception');
    }
}

解决方案的实施

提醒一下,最新代码可在我的github页面上找到

@规则代码(ExpectedTestFailureWatcher.java)

import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
// YEAH Guava!!
import static com.google.common.base.Strings.isNullOrEmpty;

public class ExpectedTestFailureWatcher implements TestRule {

    /**
     * Static factory to an instance of this watcher
     *
     * @return New instance of this watcher
     */
    public static ExpectedTestFailureWatcher instance() {
        return new ExpectedTestFailureWatcher();
    }

    @Override
    public Statement apply(final Statement base, final Description description) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                boolean expectedToFail = description.getAnnotation(ExpectedFailure.class) != null;
                boolean failed = false;
                try {
                    // allow test case to execute
                    base.evaluate();
                } catch (Throwable exception) {
                    failed = true;
                    if (!expectedToFail) {
                        throw exception; // did not expect to fail and failed...fail
                    }
                }
                // placed outside of catch
                if (expectedToFail && !failed) {
                    throw new ExpectedTestFailureException(getUnFulfilledFailedMessage(description));
                }
            }

            /**
             * Extracts detailed message about why test failed
             * @param description
             * @return
             */
            private String getUnFulfilledFailedMessage(Description description) {
                String reason = null;
                if (description.getAnnotation(ExpectedFailure.class) != null) {
                    reason = description.getAnnotation(ExpectedFailure.class).reason();
                }
                if (isNullOrEmpty(reason)) {
                    reason = 'Should have failed but didn't';
                }
                return reason;
            }
        };
    }
}


@ExpectedFailure定制注释(ExpectedFailure.java)

import java.lang.annotation.*;

/**
 * Initially this is just a marker annotation to be used by a JUnit4 Test case in conjunction
 * with ExpectedTestFailure @Rule to indicate that a test is supposed to be failing
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value = ElementType.METHOD)
public @interface ExpectedFailure {
    // TODO: enhance by adding specific information about what type of failure expected
    //Class
               assertType() default Throwable.class;

    /**
     * Text based reason for marking test as ExpectedFailure
     * @return String
     */
    String reason() default '';
}

自定义异常(可选,您可以轻松地抛出RuntimeException或现有的自定义异常)

public class ExpectedTestFailureException extends Throwable {
    public ExpectedTestFailureException(String message) {
        super(message);
    }
}

一个人不能利用预期的故障标记能力吗?

强大的功能伴随着巨大的责任 ,建议您如果不完全了解测试失败的原因,请勿将测试标记为@ExpectedFailure。 建议谨慎执行此测试方法。 请勿使用@ExpectedFailure注释替代@Ignore

未来可能的增强可能包括指定在测试用例执行期间确定的特定断言或特定消息的方法。

已知的问题

在此当前状态下,@ ExpectedFailure批注可以掩盖其他声明,并且在以后的增强功能到位之前,建议您明智地使用此方法。

参考:Mike的站点博客上,允许JUnit测试通过我们的JCG合作伙伴 Mike的失败测试案例


翻译自: https://www.javacodegeeks.com/2012/09/junit-pass-test-case-on-failures.html

junit白盒测试 案例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值