添加library,jar
@Test
它会把带有@Test的方法识别为测试方法。
assertEquals(expected, actual)
Assertion还定义了其他断言方法,例如:
· assertTrue(): 期待结果为true
· assertFalse(): 期待结果为false
· assertNotNull(): 期待结果为非null
· assertArrayEquals(): 期待结果为数组并与期望数组每个元素的值均相等
使用浮点数时,由于浮点数无法精确地进行比较
assertEquals(double expected, double actual, double delta)这个重载方法,指定一个误差值
初始化
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.2.13.RELEASE</version>
<scope>test</scope>
</dependency>
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MyStarter.class)
@WebAppConfiguration
@ComponentScan()
public class BaseTest {
public BaseRequest buildBaseQuest(String test) {
return request;
}
}
Fixture
JUnit提供了编写测试前准备、测试后清理的固定代码,我们称之为Fixture。
我们要先初始化对象,我们不必在每个测试方法中都写上初始化代码,而是通过@BeforeEach来初始化,通过@AfterEach来清理资源
JUnit还提供了@BeforeAll和@AfterAll,它们在运行所有@Test前后运行
因为@BeforeAll和@AfterAll在所有@Test方法运行前后仅运行一次,因此,它们只能初始化静态变量
因此,我们总结出编写Fixture的套路如下:
对于实例变量,在@BeforeEach中初始化,在@AfterEach中清理,它们在各个@Test方法中互不影响,因为是不同的实例;
对于静态变量,在@BeforeAll中初始化,在@AfterAll中清理,它们在各个@Test方法中均是唯一实例,会影响各个@Test方法。
大多数情况下,使用@BeforeEach和@AfterEach就足够了。只有某些测试资源初始化耗费时间太长,以至于我们不得不尽量“复用”时才会用到@BeforeAll和@AfterAll。
最后,注意到每次运行一个@Test方法前,JUnit首先创建一个XxxTest实例,因此,每个@Test方法内部的成员变量都是独立的,不能也无法把成员变量的状态从一个@Test方法带到另一个@Test方法。
异常测试
@Test
void testNegative() {
assertThrows(IllegalArgumentException.class, new Executable() {
@Override
public void execute() throws Throwable {
Factorial.fact(-1); // my function throw new IllegalArgumentException();
}
});
}
@Test
void testNegative() {
assertThrows(IllegalArgumentException.class, () -> {
Factorial.fact(-1);
});
}
条件测试
@Disabled
不让测试方法运行
为什么我们不直接注释掉@Test,而是要加一个@Disabled?这是因为注释掉@Test,JUnit就不知道这是个测试方法,而加上@Disabled,JUnit仍然识别出这是个测试方法,只是暂时不运行。它会在测试结果中显示:Tests run: 68, Failures: 2, Errors: 0, Skipped: 5
@EnabledOnOs
@DisabledOnOs(OS.WINDOWS),不在这个系统运行
@DisabledOnJre(JRE.JAVA_8):只能在Java 9或更高版本执行的测试,可以加上
@EnabledIfSystemProperty,只能在64位操作系统上执行的测试
@EnabledIfEnvironmentVariable,需要传入环境变量DEBUG=true才能执行的测试,@EnabledIfEnvironmentVariable(named = "DEBUG", matches = "true")
@Test
@EnabledOnOs(OS.WINDOWS)
void testWindows() {
assertEquals("C:\\test.ini", config.getConfigFile("test.ini"));
}
@Test
@EnabledOnOs({ OS.LINUX, OS.MAC })
void testLinuxAndMac() {
assertEquals("/usr/local/test.cfg", config.getConfigFile("test.cfg"));
}
参数化测试
如果待测试的输入和输出是一组数据: 可以把测试数据组织起来 用不同的测试数据调用相同的测试方法
参数化测试和普通测试稍微不同的地方在于,一个测试方法需要接收至少一个参数,然后,传入一组参数反复运行。
@ParameterizedTest
@ParameterizedTest
@ValueSource(ints = { 0, 1, 5, 100 })
// @ValueSource(ints = { -1, -5, -100 })
void testAbs(int x) {
assertEquals(x, Math.abs(x));
}
多参数、测试结果
@MethodSource
编写一个同名的静态方法来提供测试参数, 如果静态方法和测试方法的名称不同,@MethodSource也允许指定方法名。但使用默认同名方法最方便。
@ParameterizedTest
@MethodSource
void testCapitalize(String input, String result) {
assertEquals(result, StringUtils.capitalize(input));
}
static List<Arguments> testCapitalize() {
return List.of( // arguments:
Arguments.arguments("abc", "Abc"), //
Arguments.arguments("APPLE", "Apple"), //
Arguments.arguments("gooD", "Good"));
}
@CsvSource
它的每一个字符串表示一行,一行包含的若干参数用,分隔
@ParameterizedTest
@CsvSource({ "abc, Abc", "APPLE, Apple", "gooD, Good" })
void testCapitalize(String input, String result) {
assertEquals(result, StringUtils.capitalize(input));
}
@CsvFileSource
我们可以把测试数据提到一个独立的CSV文件中,然后标注上@CsvFileSource
@ParameterizedTest
@CsvFileSource(resources = { "/test-capitalize.csv" })
void testCapitalizeUsingCsvFile(String input, String result) {
assertEquals(result, StringUtils.capitalize(input));
}
JUnit只在classpath中查找指定的CSV文件,因此,test-capitalize.csv这个文件要放到test目录下
apple, Apple
HELLO, Hello
JUnit, Junit
reSource, Resource