使用Java 8 Lambda清理JUnit Throwable-Tests

最近,我参与了一个关于twitter和google +的简短在线讨论,其中涉及一个问题,即Java 8 Lambda表达式的到来为什么使catch-exception库 1过时了。 这是由简短的声明触发的,该声明将不再维护该库,因为lambda将使其变得多余。

当时想出的答案 RafałBorowiec在他写得很好的文章《 JUNIT:使用JAVA 8和LAMBDA表达式测试例外》中提出的答案有很多共同点。 但是,让这两种方法都重新考虑一下,我相信就干净代码而言,甚至可以做得更好。

因此,这篇文章是对该主题的引用,它分享了我的最新考虑,并简要地解释了一个稍微完善的解决方案。 这样,我希望很快就能发现薄弱环节……

动机

在编写测试时,我总是尽力在测试方法中以清晰可见的方式将布置/动作/声明 2个阶段分离开来(我的印象是,越来越多的人通过使用空白来视觉强调这些阶段)行作为分隔符)。

现在,在我看来,上面提到的catch-exception解决方案或多或少地将行为断言阶段混合在一起。 这是因为两个都声称Throwable在仍处于动作阶段时已被抛出。 但是断言显然属于断言阶段。

幸运的是,这个问题很容易解决。

细化

让我们看一个简单的示例,以解释改进的方法的外观。 我从一个类开始,该类提供了一个IllegalStateException的方法以进行演示:

public class Foo {

  static final String ERR_MESSAGE = "bad";

  public void doIt() throws IllegalStateException {
    throw new IllegalStateException(ERR_MESSAGE);
  }
}

下一个代码片段引入了一个小助手,该助手负责捕获在JUnit测试的操作阶段抛出的Throwable 。 请注意,它本身不会声明任何内容。 它仅返回捕获的Throwable如果有),否则返回null

public class ThrowableCaptor {

  public interface Actor {
    void act() throws Throwable;
  }

  public static Throwable captureThrowable( Actor actor ) {
    Throwable result = null;
    try {
      actor.act();
    } catch( Throwable throwable ) {
      result = throwable;
    }
    return result;
  }
}

为了强调ThrowableCaptor用于处理JUnit Test的动作阶段, captorThrowable方法采用了Actor类型的参数–诚然,它可能会比喻过期一些……

无论如何,有了该实用程序, AssertJ用于干净的匹配器表达式,静态导入和手头的Java 8 lambda,异常测试可能看起来像这样:

public class FooTest {

  @Test
  public void testException() {
    // arrange
    Foo foo = new Foo();
    
    // act
    Throwable actual = captureThrowable( foo::doIt );
    
    // assert
    assertThat( actual )
      .isInstanceOf( IllegalStateException.class )
      .hasMessage( Foo.ERR_MESSAGE );
  }
}

为了澄清起见,我添加了一些注释,以描述测试方法中三个阶段的明确分离。 如果没有抛出异常,则assert块将以断言错误来退出此过程,并指出“期望实际值不为null” 3

结论

通过将Throwable存在检查从行为转移到断言阶段,基于Java8 lambda表达式的catch-exception方法允许以一种非常简洁的方式编写此类测试-至少从我当前的角度来看。

所以你怎么看? 我想念什么吗?

  1. 为了使异常测试更简洁,catch-exception库在一行代码中捕获异常,并使它们可用于进一步分析
  2. 请参阅实用单元测试,第3.9章。 单元测试的阶段,Tomek Kaczanowski 2013,通常也表示为构建-操作-检查模式,清洁代码,第9章。单元测试,Robert C. Martin,2009年
  3. Assertion#isNotNull检查由Assertion#isInstanceOf隐式调用,但当然也可以显式调用

翻译自: https://www.javacodegeeks.com/2014/07/clean-junit-throwable-tests-with-java-8-lambdas.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值