简单的 JUnit 项目

回顾一下创建并运行简单的 JUnit 测试项目,先添加 JUnit 依赖然后编写类似如下模板的测试类,使用 IDE 的话直接用插件运行就行, 使用 Maven 的话运行命令 mvn test 就能看到测试结果。

public class Tests {
    @Test
    public void test() {
        // ...
    }
}

执行顺序

为满足一些测试对环境的要求,例如数据库连接及关闭,JUnit 提供了一系列注解来在测试前后进行操作,以下为注解运行的顺序的介绍。

  • @BeforeClass 运行测试类前执行且只执行一次
  • @Before 每个测试方法执行前执行
  • @Test 测试方法,每个测试方法的顺序也可以指定
  • @After每个测试方法执行后执行
  • @AfterClass 运行测试类后执行且只执行一次

上面提到测试方法也可以指定顺序,利用 @FixMethodOrder 标注测试类。

@FixMethodOrder(MethodSorters.DEFAULT)
public class Tests {
    // ...
}

MethodSorters 有三种取值,分别
代表不同的执行顺序。

  • DEFAULT 由方法名的 hashcode 值大小决定执行顺序,若值一样则根据方法名的字典顺序
  • NAME_ASCENDING 由方法名的字典顺序决定执行顺序
  • JVM 由 JVM 返回的方法名的顺序决定

断言

JUnit 的 org.junit.Assert 类提供了一系列静态方法用来断言,当断言不成立时会调用 fail 抛出 AssertionError 的异常,也可手动调用 fail 来抛出异常,下面列表为该类提供的静态方法。

  • assertTrue
  • assertFalse
  • assertNull
  • assertNotNull
  • assertSame
  • assertNotSame
  • assertEquals
  • assertArrayEquals
  • assertThat
  • fail

assertEquals 与 assertSame 区别

阅读源码可以知道,assertEquals 是调用对象的 equals 方法进行比较,而 assertSame 则是直接用 == 进行比较。

所以用 assertSame 来断言值类型或者内存地址是否相等,而用 assertEquals 来断言对象的 equals 方法是否为真。

assertThat 与 Matcher

assertThat 利用 matcher 匹配器来进行断言,其中一个方法签名如下所示。

assertThat(T actual, Matcher<T> matcher)

org.hamcrest.CoreMatchers 类中提供了匹配器静态的方法,可静态导入里头所有的方法,如下为用 assertThat 实现 assertTrue 的例子。

import static org.hamcrest.CoreMatchers.*;

public class Tests {
    @Test
    public void test() {
        assertThat(true, is(true)); // same as assertTure()
    }
}

另外还可以自定义匹配器,推荐继承 BaseMatcher<T> 抽象类而不是实现 Matcher<T> 接口,下面为一个简单的例子。

public class Tests {
    private static Contains contains(String substring) {
        return new Contains(substring);
    }
    @Test
    public void test() {
        assertThat("test", contains("t"));
    }
}

class Contains extends BaseMatcher<String> {
    private String substring;
    
    public Contains(String substring) {
        this.substring = substring;
    }
    
    @Override
    public boolean matches(Object str) {
        return ((String)str).contains(substring);
    }

    @Override
    public void describeTo(Description description) {
        // ...
    }
}

Spring Boot 使用 JUnit

Spring Boot 中无需任何配置,就能使用 JUnit 来测试,下面是 Spring Boot 项目的自带的测试模板。

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
    @Test
    public void contextLoads() {
    }
}

指定运行环境及加载配置

测试类标注了两个注解 ,JUnit 提供的 @RunWith 注解来指定运行环境,这里指定了 SpringRunner 即 Spring 的运行环境。

@SpringBootTest 注解则用来加载所需 Spring 环境所需要的配置,这样就可以在测试环境中自动装载所需要的 Bean 。

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
    @Autowired
    Foo foo;
    
    @Test
    public void contextLoads() {
        foo.bar();
    }
}

加速测试

当有些测试不需要加载整个 Spring Boot 环境时,可以将 @SpringBootTest 改用 @ContextConfiguration 注解只加载所需配置,这样可以加速测试,下面例子是只需要 DemoConf 类的配置。当完全不需要 Spring 环境来测试时,还可以去掉 @RunWith 注解。

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = DemoConf.class)
public class DemoApplicationTests {
    // ...
}