java test-2 JUnit 4&5 部分基础
dev
#java
2020/12/25
1
2
3
4
5
6
7
8
9
<dependency>
<groupId> org.junit.jupiter</groupId>
<artifactId> junit-jupiter-engine</artifactId>
</dependency>
<dependency>
<groupId> org.junit.platform</groupId>
<artifactId> junit-platform-runner</artifactId>
<scope> test</scope>
</dependency>
JUnit4和JUnit5在测试编码风格上没有太大变化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import org.junit.jupiter.api.* ;
public class AppTest {
@BeforeAll
static void setup () {
System.out.println("@BeforeAll executed" );
}
@BeforeEach
void setupThis () {
System.out.println("@BeforeEach executed" );
}
@Tag ("DEV" )
@Test
void testOne () {
}
@Tag ("PROD" )
@Disabled
@Test
void testTwo () {
}
@AfterEach
void tearThis () {
System.out.println("@AfterEach executed" );
}
@AfterAll
static void tear () {
System.out.println("@AfterAll executed" );
}
}
Assertion
org.junit.jupiter.Assertions
测试期望结果
assertEquals(expected, actual)
最常用
assertTrue()
assertFalse()
assertNotNull()
assertArrayEquals()
…
三方断言类库
JUnit Jupiter足以满足许多测试场景需要,更强大和附加功能,如匹配器,AssertJ,Hamcrest,Truth 等第三方断言库自由选择
1
2
3
4
5
6
7
8
9
10
import static org.hamcrest.CoreMatchers.equalTo ;
import static org.hamcrest.CoreMatchers.is ;
import static org.hamcrest.MatcherAssert.assertThat ;
import org.junit.jupiter.api.Test ;
@Test
void assertWithHamcrestMatcher () {
assertThat(2 + 1, is(equalTo(3)));
}
JUnit 4 编程模型遗留继续用 org.junit.Assert.assertThat
assertThrows
1
2
3
4
5
6
7
@Test
void exceptionTesting () {
Throwable exception = assertThrows(IllegalArgumentException.class, () -> {
throw new IllegalArgumentException("a message" );
});
assertEquals("a message" , exception.getMessage());
}
Fixture(生命周期相关)
用作 编写测试前准备、测试后清理的固定代码
@BeforeEach/@AfterEach和@BeforeAll/@AfterAll
实例变量,在 @BeforeEach 中初始化,在 @AfterEach中清理,它们在各个@Test方法中互不影响,因为是不同的实例
静态变量,在@BeforeAll中初始化,在@AfterAll中清理,它们在各个@Test方法中均是唯一实例,会影响各个@Test方法
大多用 @BeforeEach和 @AfterEach足够,只有某些测试资源初始化耗费时间太长,以至于不得不尽量“复用”时才用 @BeforeAll和 @AfterAll
condition
1
2
3
4
5
6
7
8
9
10
11
12
13
@Disabled
@EnabledOnOs (OS.WINDOWS)
@EnabledOnOs ({ OS.LINUX, OS.MAC })
@DisabledOnOs (OS.WINDOWS)
@DisabledOnJre (JRE.JAVA_8)
@EnabledIfSystemProperty (named = "os.arch" , matches = ".*64.*" )
@EnabledIfEnvironmentVariable (named = "DEBUG" , matches = "true" )
测试方法、测试类、测试集、测试运行器(Runners)
测试方法就是用@Test注解的一些函数
测试类是包含一个或多个测试方法的一个 **Test.java文件
测试集是一个suite,可能包含多个测试类
测试运行器则决定了用什么方式偏好去运行这些测试集/类/方法
常见 Runners
@RunWith(Parameterized.class) 配合@Parameters使用JUnit的参数化功能
@RunWith(Suite.class)
@SuiteClasses({ATest.class,BTest.class,CTest.class})
@RunWith(JUnit4.class) junit4的默认运行器
@RunWith(JUnit38ClassRunner.class),兼容junit3.8
@RunWith(SpringJUnit4ClassRunner.class)集成了spring的一些功能
JUnit 3 默认 JUnit4ClassRunner
JUnit4默认 BlockJUnit4ClassRunner
1
JUnit4 extends BlockJUnit4ClassRunner
@RunWith(JUnit4.class) 即调用默认JUnit 运行器
参数化测试
@ParameterizedTest
@ValueSource
@MethodSource
@CsvSource
1
2
3
4
5
@ParameterizedTest
@ValueSource(ints = { 0, 1, 5, 100 })
void testAbs(int x) {
assertEquals(x, Math.abs(x));
}
1
2
3
4
5
6
7
8
public class StringUtils {
public static String capitalize(String s) {
if (s.length() == 0) {
return s;
}
return Character.toUpperCase(s.charAt(0)) + s.substring(1).toLowerCase();
}
}
参数化测试,不但要给出输入,还要给出预期输出。测试方法至少需要接收两个参数:
1
2
3
4
@ParameterizedTest
void testCapitalize (String input, String result) {
assertEquals(result, StringUtils.capitalize(input));
}
@MethodSource
,写个同名静态方法提供测试参数:
1
2
3
4
5
6
7
8
9
10
11
12
@ParameterizedTest
@MethodSource
void testCapitalize(String input, String result) {
assertEquals(result, StringUtils.capitalize(input));
}
static List<Arguments> testCapitalize() {
return asList(
Arguments.arguments("abc", "Abc"),
Arguments.arguments("APPLE", "Apple"),
Arguments.arguments("gooD", "Good"));
}
1
2
@CsvSource ({ "abc, Abc" , "APPLE, Apple" , "gooD, Good" })
@CsvFileSource (resources = { "/test-capitalize.csv" })
Categories
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public interface FastTests { /* category marker */ }
public interface SlowTests { /* category marker */ }
public class A {
@Test
public void a () {
fail();
}
@Category (SlowTests.class)
@Test
public void b () {
}
}
@Category ({SlowTests.class, FastTests.class})
public class B {
@Test
public void c () {
}
}
@RunWith (Categories.class)
@IncludeCategory (SlowTests.class)
@SuiteClasses ( { A.class, B.class })
public class SlowTestSuite {
// Will run A.b and B.c, but not A.a
}
@RunWith (Categories.class)
@IncludeCategory (SlowTests.class)
@ExcludeCategory (FastTests.class)
@SuiteClasses ( { A.class, B.class })
public class SlowTestSuite {
// Will run A.b, but not A.a or B.c
}
测试套件
1
2
3
4
@RunWith (JUnitPlatform.class)
@SelectPackages ("junit5.examples" )
public class JUnit5TestSuiteExample {
}
过滤测试包、类甚至测试方法
@IncludePackages
和@ExcludePackages
来过滤包
@IncludeClassNamePatterns
和@ExcludeClassNamePatterns
过滤测试类
@IncludeTags
和@ExcludeTags
过滤测试方法
1
2
3
4
5
6
@RunWith (JUnitPlatform.class)
@SelectPackages ("junit5.examples" )
@IncludePackages ("junit5.examples.packageA" )
@ExcludeTags ("PROD" )
public class JUnit5TestSuiteExample {
}
maven FailSafe & Surefire
Surefire插件用来执行单元测试
FailSafe插件用来执行集成测试
maven的生命周期与集成测试相关的四个阶段
1.pre-integration-test:准备集成测试环境,类似于junit单元测试中的setUp
2.integration-test:执行集成测试
3.post-integration-test:销毁集成测试的环境,类似于junit单元测试中的tearDown
4.校验:分析集成测试的结果
FailSafe工作在integration-test以及verify阶段,与surefire插件不同的是不会因为集成测试中失败而终止整个过程,即post-integration-test可以确定执行
FailSafe插件有两个goal:integration-test 和verify
1、3 如通过容器插件,jetty/tomcat plugin 或cargo plugin实现
2、4由failsafe实现
cargo可加载命令行参数,通过jacoco统计测试覆盖率,tomcat plugin就无法做到
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<plugin>
<groupId> org.apache.maven.plugins</groupId>
<artifactId> maven-failsafe-plugin</artifactId>
<executions>
<execution>
<id> integration-test</id>
<goals>
<goal> integration-test</goal>
</goals>
</execution>
<execution>
<id> verify</id>
<goals>
<goal> verify</goal>
</goals>
</execution>
</executions>
</plugin>
IT用例如果和UT用例放在同项目,必须在在UT的surefire中exclude所有的IT用例
spring boot service注入
junit5
1
@ExtendWith (SpringExtension.class)
junit4
1
@RunWith (SpringRunner.class)
不加,service无法注入,值为null
ref
https://www.cnblogs.com/felixzh/p/12554701.html
https://zhuanlan.zhihu.com/p/162032557
https://www.baeldung.com/junit-5-migration
https://blog.csdn.net/HeatDeath/article/details/79841526
https://www.cnblogs.com/lspz/p/6727123.html
http://www.jfh.com/jfperiodical/article/1455 ?
https://doczhcn.gitbook.io/junit5/index/index
蔡志忠 道德经漫画 签名、作画
java test-1 JUnit 简介