junit 预期错误_谨慎使用JUnit的预期异常

junit 预期错误

有时,当我们收到对jOOQ或其他库的拉取请求时,人们会将单元测试中的代码更改为更“惯用的JUnit”。 特别是,这意味着他们倾向于更改此代码(公认的不是那么漂亮的代码):

@Test
public void testValueOfIntInvalid() {
    try {
        ubyte((UByte.MIN_VALUE) - 1);
        fail();
    }
    catch (NumberFormatException e) {}
    try {
        ubyte((UByte.MAX_VALUE) + 1);
        fail();
    }
    catch (NumberFormatException e) {}
}

…成为“更好”和“更清洁”的版本:

@Test(expected = NumberFormatException.class)
public void testValueOfShortInvalidCase1() {
    ubyte((short) ((UByte.MIN_VALUE) - 1));
}

@Test(expected = NumberFormatException.class)
public void testValueOfShortInvalidCase2() {
    ubyte((short) ((UByte.MAX_VALUE) + 1));
}

我们获得了什么?

没有!

当然,我们已经必须使用@Test批注,因此我们不妨使用其expected的属性吧? 我声称这是完全错误的。 有两个原因。 当我说“两个”时,我的意思是“四个”:

1.在代码行数方面,我们并没有真正获得任何好处

比较语义上有趣的位:

// This:
try {
    ubyte((UByte.MIN_VALUE) - 1);
    fail("Reason for failing");
}
catch (NumberFormatException e) {}

// Vs this:
@Test(expected = NumberFormatException.class)
public void reasonForFailing() {
    ubyte((short) ((UByte.MAX_VALUE) + 1));
}

给定或采用空格格式,基本语义信息量完全相同:

  1. 该方法正在测试中的ubyte() 。 这不会改变
  2. 我们要传递给失败报告的消息(以字符串或方法名称的形式)
  3. 异常类型和预期的事实

因此,即使从样式角度来看,这也不是真正有意义的更改。

2.无论如何我们都必须将其重构

在注释驱动的方法中,我所能做的就是测试异常类型 。 例如,在以后要添加更多测试的情况下,我无法对异常消息做出任何假设。 考虑一下:

// This:
try {
    ubyte((UByte.MIN_VALUE) - 1);
    fail("Reason for failing");
}
catch (NumberFormatException e) {
    assertEquals("some message", e.getMessage());
    assertNull(e.getCause());
    ...
}
3.单一方法调用不是单位

单元测试称为testValueOfIntInvalid() 。 因此, 通常在输入无效的情况下,要测试的语义“单位”是UByte类型的valueOf()行为的语义“单位”。 不适用于单个值,例如UByte.MIN_VALUE - 1

不应将其拆分为更小的单元,仅仅是因为这是我们可以将@Test注释刺入其功能范围的唯一方法。

TDD伙计们,请听听。 我从不希望将我的API设计或我的逻辑塞进由“向后”测试框架(不是个人的,JUnit)强加的一些怪异的限制。 永不 ! “我的” API比“您的”测试重要100倍。 这包括我不想:

  • 公开一切
  • 使一切都没有定论
  • 使一切都可以注射
  • 使所有内容均为非静态
  • 使用注释。 我讨厌注解。

不。 你错了。 Java已经不是一种太复杂的语言,但是让我至少可以使用我想要的任何方式使用它提供的一些功能。

不要因为测试而在我的代码上强加您的设计或语义上的毁损。

好。 我React过度了。 我总是在带有批注的情况下 。 因为…

4.对于控制流结构而言,注释始终是错误的选择

一次又一次,我为Java生态系统中的注释滥用而感到惊讶。 注释对于三件事有好处:

  1. 可处理的文档(例如@Deprecated
  2. 方法,成员,类型等的自定义“修饰符”(例如@Override
  3. 面向方面的编程(例如@Transactional

并且要注意,@ @Transactional是使其成为主流的少数几个真正有用的方面之一(日志挂钩是另一个方面,或者,如果绝对必须的话,可以进行依赖注入)。 在大多数情况下,AOP是解决问题的利基技术,您通常在普通程序中不希望这样做。

用注解对控制流结构进行建模绝对不是一个好主意,更不用说测试行为了

是。 Java已经采用了很长的(缓慢的)方法来包含更复杂的编程习惯。 但是,如果您对单元测试中偶尔的try { .. } catch { .. }语句的冗长内容感到不满,那么您可以找到解决方案。 是Java 8。

如何用Java 8更好地做

JUnit lambda正在开发中: http : //junit.org/junit-lambda.html

他们将新的功能性API添加到新的Assertions类中: https : //github.com/junit-team/junit-lambda/blob/master/junit5-api/src/main/java/org/junit/gen5/api /Assertions.java

一切都基于Executable功能接口

@FunctionalInterface
public interface Executable {
    void execute() throws Exception;
}

该可执行文件现在可以用于实现断言引发(或不引发)异常的代码。 请参见Assertions的以下方法

public static void assertThrows(Class<? extends Throwable> expected, Executable executable) {
    expectThrows(expected, executable);
}

public static <T extends Throwable> T expectThrows(Class<T> expectedType, Executable executable) {
    try {
        executable.execute();
    }
    catch (Throwable actualException) {
        if (expectedType.isInstance(actualException)) {
            return (T) actualException;
        }
        else {
            String message = Assertions.format(expectedType.getName(), actualException.getClass().getName(),
                "unexpected exception type thrown;");
            throw new AssertionFailedError(message, actualException);
        }
    }
    throw new AssertionFailedError(
        String.format("Expected %s to be thrown, but nothing was thrown.", expectedType.getName()));
}

而已! 现在,那些反对try { .. } catch { .. }块的冗长的人可以重写此代码:

try {
    ubyte((UByte.MIN_VALUE) - 1);
    fail("Reason for failing");
}
catch (NumberFormatException e) {}

…进入:

expectThrows(NumberFormatException.class, () -> 
    ubyte((UByte.MIN_VALUE) - 1));

如果我想对异常进行进一步检查,可以这样做:

Exception e = expectThrows(NumberFormatException.class, () -> 
    ubyte((UByte.MIN_VALUE) - 1));
assertEquals("abc", e.getMessage());
...

出色的工作,JUnit lambda团队!

函数式编程每次都会击败注释

注释被滥用了很多逻辑 ,主要是在JavaEE和Spring环境中,它们都非常渴望将XML配置移回Java代码。 这是错误的方法,这里提供的示例清楚地表明,与使用批注相比,几乎总是有一种更好的方法可以使用面向对象或功能编程来显式地写出控制流逻辑。

@Test(expected = ...)的情况下,我得出结论:

安息, expected

(无论如何,它不再是JUnit 5 @Test批注的一部分)

翻译自: https://www.javacodegeeks.com/2016/01/use-junits-expected-exceptions-sparingly.html

junit 预期错误

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值