Assertj了解

单元测试

一个单元测试分三步:

  1. 准备数据
  2. 执行测试方法
  3. 断言测试结果

Java里面写单元测试都会以来JUnit,而且该包夜提供了一些的Assert的API。但不得不说确实不好用,可读性差。所以不推荐使用。很多人也喜欢用Hamcrest,非常好用(我现在还是用它)。遗憾的是从2012年开始就没有后续更新了。之后了FEST,只是它也不更新了。前段时间去ThoughtWorks 面试,发现他们提倡用 Assertj。这里整理下。

Assertj

Assertj 号称"Java的流水式断言“,目前最新版本是 3.10.0,从 assertj 3 开始支持JDK8。Github上也有很多下载。在项目中引入Assertj,只需添加如下依赖:

<!-- https://mvnrepository.com/artifact/org.assertj/assertj-core -->
<dependency>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-core</artifactId>
    <version>3.10.0</version>
    <scope>test</scope>
</dependency>

看个例子,构造一个 PersonInfo 对象,包含三个属性,然后验证其属性。

public class PersonInfo {
    private String name;
    private int age;
    private Date birthDate;
    // 省略其他
}

对应测试用例:

    @Test
    public void testPersonInfo() {
        // 准备数据
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(1998, Calendar.JULY, 13);
        Date date = calendar.getTime();
 
        // 获取对象
        PersonInfo ka = new PersonInfo("KaKa", 21, date);
 
        // 断言
        assertThat(ka).isNotNull().isInstanceOf(PersonInfo.class);// Object/Class
        assertThat(ka.getName()).startsWith("K").contains("a").isEqualTo("KaKa");// String
        assertThat(ka.getAge()).isPositive().isGreaterThan(20).isGreaterThanOrEqualTo(21);// int
        assertThat(ka.getBirthDate()).isBeforeYear(2000).isInSameMonthAs("1998-07-01").isInSameDayAs(date);// java.util.Date
    }

是不是很简单?这种流水式或者说链式断言用起来非常方便。
注意,这里 assertThat 是 import static org.assertj.core.api.Assertions.assertThat;

API

assertj 断言支持字符串、数字、日期、List、Map、Class等类型,此外还提供了好用的 fail 方法。除此之外,对Java中的Exception、Iterable、JodaTime、Guava等都提供支持。下边看些例子:

上边例子中已经介绍了字符串、数字和日期的断言。此处省略。

List

例如:

    @Test
    public void testList() {
        List<String> names = Arrays.asList("zhangsan", "lisi", "wangwu", "zhaoliu");
        // assertj 3 需要加 asList()
        assertThat(names).asList()
                .hasSize(4).startsWith("zhangsan").endsWith("zhaoliu")
                .contains("lisi", atIndex(1))
                .containsOnlyOnce("wangwu");
    }

Map

例如:

    @Test
    public void testMap() {
        Map<String, String> map = new HashMap();
        map.put("a", "A");
        map.put("b", "B");
        map.put("c", "C");
 
        assertThat(map).extracting("a", "b", "c").contains("A").doesNotContain("D");
        assertThat(map).satisfies(s -> s.containsKey("b")).extracting("b").contains("B");
    }

Class

例如

    @Test
    public void testClass() {
        // 断言 不是注解类
        assertThat(PersonInfo.class).isNotAnnotation();
 
        // 断言 不是注解类
        assertThat(Deprecated.class).isAnnotation();
 
        // 断言 存在注解 @Deprecated
        assertThat(PersonInfo.class).hasAnnotation(Deprecated.class);
 
        // 断言 不是接口
        assertThat(PersonInfo.class).isNotInterface();
 
        // 断言 Object 类是 PersonInfo 类的父类
        assertThat(Object.class).isAssignableFrom(PersonInfo.class);
    }

Fail

例如:

    @Test
    public void testFail() {
        try {
            fail("在不检查任何条件的情况下使断言失败。显示一则消息");
        } catch (AssertionError ae) {
            System.out.println(ae);// 会有输出
        }
        try {
            failBecauseExceptionWasNotThrown(RuntimeException.class);
        } catch (AssertionError ae) {
            System.out.println(ae);// 会有输出
        }
    }

Exception

Junit自带的就已经支持exception的处理。有意思的是,除了正常方法,它还可以接受各种 lamda 表达式。

    // 该例子来源于官网
    @Test
    public void testException() {
        assertThatExceptionOfType(IOException.class).isThrownBy(() -> { throw new IOException("boom!"); })
                .withMessage("boom!")
                .withMessageContaining("oom")
                .withMessage("%s!", "boom")
                .withStackTraceContaining("IOException")
                .withNoCause();
    }

如果编译器不支持 JDK8,可以在 pom.xml 中加入插件

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>2.3.2</version>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

用了这么久,觉得 assertj 非常好用,可读性也高。只是个人在写的时候喜欢 debug,而 assertj 查看中间结果时都是函数式的,不容易看数据。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值