IDEA中的JUnit 4单元测试

IDEA中的JUnit 4单元测试


(一)导入Maven依赖

1
2
3
4
5
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>

(二)JUnit语法

JUnit是基于Java开发的单元测试框架,它是白盒测试的一种,程序员知道被测试的代码需要完成什么功能、怎么完成。

1.注解

(1)@Test

测试方法。

测释方法之前都必须用@Test修饰;且测试方法必须是public void的,不允许带任何参数

  1. (expected = XXException.class):如果程序异常和XXException一样,则测试通过
  2. (timeout = 100):如果程序的执行能在100毫秒内完成,则测试通过

(2)@Ignore

被忽略的测试方法:加上之后,暂不测试此段代码

(3)@Before

在每一个测试方法之前都执行一次,只需声明为public

(4)@After

在每一个测试方法之后都执行一次,只需声明为public

(5)@BeforeClass

对于所有测试方法前只运行一次,要声明为public static

(6)@AfterClass

对于所有测试方法后只运行一次,要声明为public static


2.参数断言

  1. Assert.assertEquals(param, expectedValue):其中param是需要判断的字段,expectedValue是期待的值。
    它就等价于if(param == expectedValue) {//right!}
  2. Assert.assertTrue(...)/Assert.assertFalse(...)

3.Demo

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
public CalTest() {
Calculator c = null;

//每个方法之前
@Before
public void before() {
c = new Calculator();
}

//测试某个方法,期待算术异常
@Test(timeout = 50, expected = ArithmeticException.class)
public void testAdd() {
int result = c.add(1, 2);
//参数断言
Assert.assertEquals(result, 3);
//抛出异常
throw new ArithmeticException();
}

//在每个方法之后
@After
public void after() {
System.out.println("Done!");
}
}

4.JUnitIDEA中实现代码覆盖

步骤

  1. 新建文件夹,右键 -> Mark Directory as -> Test Resources Root
  2. 待测试类中Ctrl + Shift + T创建测试类
  3. 点击工具栏左上角的Edit Configuration

EditConfig

  1. 点击Configuration中的Class选项后的···,选择测试类。

conf

  1. Code Coverage中选择tracing模式。

  2. Code Coverage,点击第一个+,选择想要显示覆盖率的业务类。

cover

  1. 点击测试方法左边的三角形符号,Run xxx with Coverage即可。测试通过后,在业务类中,已覆盖的代码会用绿色标识,未覆盖是红色。

runtest

  1. 如果报错Verify Error,将vm参数从-ea修改为-noverify

代码覆盖Demo:

1.public方法测试:getDetailBeanFromListT

如果是public static,直接通过类调用;如果是non-static,通过类对象调用。

待测试业务方法:

1
2
3
4
5
6
7
8
9
10
11
12
public static <T extends O2ODetailCommom> T getDetailBeanFromListT(List<T> itemList, String itemNo) {
if (StringUtil.isBlank(itemNo) || CollectionUtils.isEmpty(itemList)) {
return null;
}
String trimItemNo = itemNo.trim();
for (O2ODetailCommom itemBean : itemList) {
if (trimItemNo.equalsIgnoreCase(itemBean.getItemNo())) {
return (T)itemBean;
}
}
return null;
}

JUnit测试方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Test
public void testGetDetailBeanFromListT(){
List<O2OSettleCartDetailBean> itemList = new ArrayList<O2OSettleCartDetailBean>();
//itemNo Blank
PublicSettleUtil.getDetailBeanFromListT(itemList, "");
//itemNo notBlank
PublicSettleUtil.getDetailBeanFromListT(itemList, "1");
//itemList not null
O2OSettleCartDetailBean detail = new O2OSettleCartDetailBean();
detail.setItemNo("1111");
itemList.add(detail);
PublicSettleUtil.getDetailBeanFromListT(itemList, "1111");
PublicSettleUtil.getDetailBeanFromListT(itemList, "1");
}
2.private方法测试:反射调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//测试私有函数 —— 反射

//实例化 私有方法 所属类 的 对象
ServiceImpl impl = new ServiceImpl();
//私有方法参数
Param p = new Param();

//通过反射获取私有方法
//Class.class.getDeclaredMethod("methodName",Param.class)
Method method = ServiceImpl.class.getDeclaredMethod("methodName",Param.class);

//private修饰的变量,需要setAccessible(true)才能访问
method.setAccessible(true);
//通过invoke(ClassInstance ci, Param p)反射调用
method.invoke(impl, p);

(三)JUnit 5单元测试

  • JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
  • JUnit 5要求JDK8以上

    JUnit 5JUnit 4的不同参考JUnit 5 vs JUnit 4

pom.xml添加Maven依赖

1
2
3
4
5
6
7
8
9
10
11
12
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.jupiter.version}</version>
</dependency>

<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>${junit.platform.version}</version>
<scope>test</scope>
</dependency>

如果是Spring Boot,直接引入spring-boot-starter-test依赖就可以同时导入JUnitMockito

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>

函数注解

  1. @BeforeEach:每个测试方法运行前执行一次此方法,一定不能是static方法,否则抛出RuntimeException

    等同于JUnit 4@Before

  2. @AfterEach:每个测试方法运行后执行一次此方法,一定不能是static方法,否则抛出RuntimeException

    等同于JUnit 4@After

  3. @BeforeAll:所有测试方法运行前执行一次此方法,必须是static方法,否则抛出RuntimeException

    等同于JUnit 4@BeforeClass

  4. @AfterAll:所有测试方法运行后执行一次此方法,必须是static方法,否则抛出RuntimeException

    等同于JUnit 4@AfterClass

  5. @Test:指明方法是JUnit测试方法

  6. @DisplayName用于给测试类或测试方法提供自定义显示

  7. @Disable:忽略某一个测试方法

    等同于JUnit 4@Ignore

  8. @Nested嵌套测试类

  9. @Tag为测试类或测试方法添加标签(比如DEV环境/PROD环境),方便发现和过滤;同一个方法可以有多个标签

  10. @TestFacotry动态测试的测试工场

  11. @RepeatTest(value = 5, name = "{displayName} - {currentRepetition} of {totalRepetitions}")重复测试n次,每次显示的名称是name

    @RepeatTest是尚处于测试阶段的注解


类注解

  1. @SelectPackages({"pack-a","pack-b"}):选择测试包
  2. @SelectClasses:选择测试类
  3. @RunWith(JUnitPlatform.class)运行JUnit测试
  4. @IncludePackages/@ExcludePackages:过滤测试包
  5. @IncludeClassNamePatterns/@ExcludeClassNamePatterns:过滤测试类
  6. @IncludeTags/@ExcludeTags根据@Tag注解过滤测试方法
  7. @Disable:忽略整个类的测试方法
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
42
43
44
45
46
47
@RunWith(JUnitPlatform.class)
@ExcludeTag("PROD")
public class FxxkTest {

//必须是static方法,否则抛出RuntimeException
@BeforeAll
static void setup() {
System.out.println("@BeforeAll");
}

//一定不能是static方法,否则抛出RuntimeException
@BeforeEach
void setupThis() {
System.out.println("@BeforeEach");
}

@Tag("DEV")
@DisplayName("test 1")
@RepeatTest(value = 5, name = "{displayName} - {currentRepetition} of {totalRepetitions}")
@Test
void testCalOne() {
System.out.println("==========TEST ONE EXECUTED==========");
Assertions.assertEquals(4, Fxxk.add(2, 2));
}

@Tag("PROD")
@DisplayName("test 2")
@RepeatTest(value = 5, name = "{displayName} - {currentRepetition} of {totalRepetitions}")
@Disabled
@Test
void testCalTwo() {
System.out.println("==========TEST TWO EXECUTED==========");
Assertions.assertEquals(6, Fxxk.add(4, 2));
}

//一定不能是static方法,否则抛出RuntimeException
@AfterEach
void tearThis() {
System.out.println("@AfterEach");
}

//必须是static方法,否则抛出RuntimeException
@AfterAll
static void tear() {
System.out.println("@AfterAll");
}
}

断言:Assertions

  1. Assertions.assertEquals()
  2. Assertions.assertNotEquals()
1
2
3
4
5
6
7
8
9
10
void testCase() {
//pass
Assertions.assertNotEquals(3, Fxxk.add(2,2));
Assertions.assertEquals(4, Fxxk.add(2,2));
//fail
Assertions.assertNotEquals(4, Fxxk.add(2,2), "test failed");
//fail
Supplier<String> msgSupplier = () -> "test failed!";
Assertions.assertNotEquals(4, Fxxk.add(2,2), msgSupplier);
}
  1. Assertions.assertThrows(Exception.class, code)断言代码将抛出某种异常

  2. Assertions.assertArrayEquals()

  3. Assertions.assertIterableEquals()

  4. Assertions.assertLinesMatch()

  5. Assertions.assertNotNull()

  6. Assertions.assertNull()

  7. Assertions.assertSame()断言两个Object相同

    a == b

  8. Assertions.assertNotSame()断言两个Object不相同

  9. Assertions.assertTrue()

  10. Assertions.assertFalse()


假设:Assumptions

传入一个boolean类型的参数:

  1. Assumptions.assumeTrue()
  2. Assumptions.assumeFalse()
  3. Assumptions.assumeThat()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
void testOnDev()
{
System.setProperty("ENV", "DEV");
Assumptions.assumeTrue("DEV".equals(System.getProperty("ENV")));
//继续
}

@Test
void testOnProd()
{
System.setProperty("ENV", "PROD");
Assumptions.assumeTrue("DEV".equals(System.getProperty("ENV")));
//终止
}
-------------本文结束感谢您的阅读-------------

本文标题:IDEA中的JUnit 4单元测试

文章作者:DragonBaby308

发布时间:2019年09月25日 - 12:52

最后更新:2020年01月25日 - 13:23

原始链接:http://www.dragonbaby308.com/junit/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

急事可以使用右下角的DaoVoice,我绑定了微信会立即回复,否则还是推荐Valine留言喔( ఠൠఠ )ノ
0%