浅谈单元测试 Junit4

article/2025/10/2 10:56:35

在这里插入图片描述

JUint是Java编程语言的单元测试框架,用于编写和运行可重复的自动化测试。本文主要针对Junit4要点进行梳理总结。

一、浅谈单元测试

1.1 什么是单元测试

  单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单元指一个函数,Java里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。总的来说,单元就是人为规定的最小的被测功能模块。单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。

1.2 为什么要写单元测试

  这其实是问单元测试能带来什么好处,之所以把这个问题放在这里讨论,是因为需要清楚单元测试的使用场景,以及它做得到和做不到的。我们在写好一个函数或者类以后,需要检验我们的程序是否存在bug或者是否满足我们的需求,通常的做法就是将写好的函数在mian方法中调用,输入一些测试用例进行检验。当要检验的方法数量较少时,这种方法可行,但是当我们有大量的函数需要验证时,该方法就显得笨重且繁琐,往往需要我们人工检查输出的结果是否正确等,比较混乱。因此,单元测试就是用来解决这种繁琐问题的。使用单元测试可以有效地降低程序出错的机率,提供准确的文档,并帮助我们改进设计方案等等。以下列举了一些我为什么使用单元测试的好处:

  • 允许你对代码做出较任何改变,因为你了解单元测试会在你的预期之中。
  • 单元测试可以有效地降低程序出现BUG的机率。
  • 帮助你更深入地理解代码,因为在写单元测试的时候,你需要明确程序所有的执行流程及对应的执行结果等等。
  • 允许在任何时候代码重构,而不必担心破坏现有的代码,这使得我们编写程序更灵活。
  • 确保你的代码的健壮性,因为所有的测试都是通过了的。

1.3 什么时候写单元测试

写单元测试的时机不外乎三种情况:

  • 一是在具体实现代码之前,这是测试驱动开发(TDD)所提倡的;
  • 二是与具体实现代码同步进行。先写少量功能代码,紧接着写单元测试(重复这两个过程,直到完成功能代码开发)。其实这种方案跟第一种已经很接近,基本上功能代码开发完,单元测试也差不多完成了。
  • 三是编写完功能代码再写单元测试。我的实践经验告诉我,事后编写的单元测试“粒度”都比较粗。对同样的功能代码,采取前两种方案的结果可能是用10个“小”的单测来覆盖,每个单测比较简单易懂,可读性可维护性都比较好(重构时单测的改动不大);而第三种方案写的单测,往往是用1个“大”的单测来覆盖,这个单测逻辑就比较复杂,因为它要测的东西很多,可读性可维护性就比较差。

个人比较推荐单元测试与具体实现代码同步进行这个方案的,只有对需求有一定的理解后才能知道什么是代码的正确性,才能写出有效的单元测试来验证正确性,而能写出一些功能代码则说明对需求有一定理解了。

二、初识 Junit4

2.1 什么是JUnit

JUint是Java编程语言的单元测试框架,用于编写和运行可重复的自动化测试。其具有如下特点:

  • 提供注解来识别测试方法。
  • 提供断言来测试预期结果。
  • JUnit 测试允许你编写代码更快,并能提高质量。
  • JUnit 优雅简洁。没那么复杂,花费时间较少。
  • JUnit测试可以自动运行并且检查自身结果并提供即时反馈。所以也没有必要人工梳理测试结果的报告。
  • JUnit测试可以被组织为测试套件,包含测试用例,甚至其他的测试套件。
  • JUnit在一个条中显示进度。如果运行良好则是绿色;如果运行失败,则变成红色。

2.2 官方资料

最好的资料依然在Junit官方网站,以下我帮你总结下Junit相关的官方网址。

网址说明
https://junit.org/junit4/官网地址
https://junit.org/junit4/docs/current/user-guide/官方入门文档
https://github.com/junit-team官方github

2.3 常用注解

Junit4 注解提供了书写单元测试的基本功能,这里列出一些常用的注解,如下表所示:

注解说明
@Test测试注解,标记一个方法可以作为一个测试用例
@Ignore暂不执行该方法
@BeforeClass在所有测试之前,只执行一次,且必须为static void
@AfterClass在所有测试之后,只执行一次,且必须为 static void
@Before该方法必须在类中的每个测试之前执,以便执行某些必要的先决条件
@After该方法在每项测试后执行(如执行每一个测试后重置某些变量,删除临时变量等)
@Runwith测试类的初始化。在测试类的开头标注,表明运行环境
@Parameters指定测试类的测试数据集合
@FixMethodOrder指定测试方法的执行顺序

三、编写单元测试

3.1 引入相关依赖

  现在主流的IDE比如IDEA或者Eclipse都提供了对JUnit4的支持,可以非常方便的使用JUnit4。当你在代码中添加了@Test注解,然后使用IDE的自动补全功能时,一般情况下IDE会弹出对话框询问你是否将JUnit4库添加到项目的类路径下。当然也可以自己手动添加JUnit4的依赖。如果使用Maven,添加如下一段:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>MavenDemo</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency></dependencies>
</project>

3.2 编写测试类

  一个 JUnit 测试是一个在专用于测试的类中的一个方法, 并且这个方法被 @org.junit.Test 注解标注。我们只需要在我们要测试的方法上加上 @Test 注解,那么这个方法就会被当做一个单元测试,单独去运行,我们来试一下。

import org.junit.Test;
import static org.junit.Assert.assertEquals;public class HelloWorldTest {@Testpublic void firstTest() {assertEquals(2, 1 + 1);}
}

@Test注解在方法上标记方法为测试方法,以便构建工具和 IDE 能够识别并执行它们。在 Junit 3中,是通过对测试类和测试方法的命名来确定是否是测试,且所有的测试类必须继承junit的测试基类。在 Junit 4中,定义一个测试方法变得简单很多,只需要在方法前加上@Test就行了。注意:测试方法必须是public void,即公共、无返回数据

3.3 测试生命周期

  JUnit4测试用例的完整的生命周期要经历几个阶段,他们分别是类级初始化资源处理、方法级初始化资源处理、执行测试用例中的方法、方法级销毁资源处理、类级销毁资源处理等。这几个阶段分别有对应的注解所标注,如下表

注解说明
@BeforeClass该方法只执行一次,并且在所有方法之前执行,例如创建数据库连接、读取文件等。
@AfterClass该方法只执行一次,并且在所有方法之后执行。通常用来对资源进行释放,比如数据库连接的关闭等。
@Before该方法在每一个测试方法之前运行,可以使用该方法进行初始化之类的操作
@After该方法在每一个测试方法之后运行,可以使用该方法进行释放资源,回收内存之类的操

简单来说,使用@BeforeClass 和 @AfterClass 两个注解标注的方法会在所有测试方法执行前后各执行一次,使用@Before 和 @After 两个注解标注的方法会在每个测试方法执行前后都执行一次。

import org.junit.*;public class StandardTest {@BeforeClasspublic static void beforeClass() {System.out.println("@BeforeClass 方法被执行");}@AfterClasspublic static void afterClass() {System.out.println("@AfterClass 方法被执行");}@Beforepublic void before() {System.out.println("@Before 单元测试开始前相关操作...");}@Afterpublic void after() {System.out.println("@After 单元测试结束后相关操作...");}@Testpublic void testCase1() {System.out.println("in test case 1");}@Testpublic void testCase2() {System.out.println("测试生命周期");}
}

这里有如下几点注意事项:

  • 父类的@BeforeClass注解方法会在子类的@BeforeClass注解方法执行前执行。
  • 父类@Before修饰的方法会在子类@Before修饰的方法执行前执行。
  • 父类@After修饰的方法会在子类@After修饰的方法执行后执行。
  • 父类中的被@AfterClass注解方法修饰的方法会在子类的@AfterClass注解修饰的方法执行之后才会被执行。

3.4 断言测试

断言测试注解如下表所示:

断言描述
void assertEquals()如果比较的两个对象是相等的,此方法将正常返回,否则测试将中止
void assertTrue()断言if条件或变量是否是true
void assertFalse()断言if条件或变量是否是false
void assertNotNull()断言一个对象不为空(null)
void assertNull()断言一个对象为空(null)
void assertSame()断言两个对象引用相同的对象
void assertNotSame()断言两个对象不是引用同一个对象
void assertArrayEquals()比较两个数组,如果它们相等,则该方法将继续进行不会发出错误,否则中止测试
import org.hamcrest.core.CombinableMatcher;
import org.junit.Test;
import java.util.Arrays;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;public class AssertionTest {@Testpublic void testAssertArrayEquals() {byte[] expected = "trial".getBytes();byte[] actual = "trial".getBytes();assertArrayEquals("failure - byte arrays not same", expected, actual);}@Testpublic void testAssertEquals() {assertEquals("failure - strings are not equal", "text", "text");}@Testpublic void testAssertFalse() {assertFalse("failure - should be false", false);}@Testpublic void testAssertNotNull() {assertNotNull("should not be null", new Object());}@Testpublic void testAssertNotSame() {assertNotSame("should not be same Object", new Object(), new Object());}@Testpublic void testAssertNull() {assertNull("should be null", null);}@Testpublic void testAssertSame() {Integer aNumber = Integer.valueOf(768);assertSame("should be same", aNumber, aNumber);}@Testpublic void testAssertThatBothContainsString() {assertThat("albumen", both(containsString("a")).and(containsString("b")));}@Testpublic void testAssertThatHasItems() {assertThat(Arrays.asList("one", "two", "three"), hasItems("one", "three"));}@Testpublic void testAssertThatEveryItemContainsString() {assertThat(Arrays.asList(new String[]{"fun", "ban", "net"}), everyItem(containsString("n")));}@Testpublic void testAssertThatHamcrestCoreMatchers() {assertThat("good", allOf(equalTo("good"), startsWith("good")));assertThat("good", not(allOf(equalTo("bad"), equalTo("good"))));assertThat("good", anyOf(equalTo("bad"), equalTo("good")));assertThat(7, not(CombinableMatcher.<Integer>either(equalTo(3)).or(equalTo(4))));assertThat(new Object(), not(sameInstance(new Object())));}@Testpublic void testAssertTrue() {assertTrue("failure - should be true", true);}
}

3.5 参数化测试

  为保证单元测试的严谨性,通常会模拟不同的测试数据来测试方法的处理能力,为此我们需要编写大量的单元测试的方法。可是这些测试方法都是大同小异的,它们的代码结构都是相同的,不同的仅仅是测试数据和期望值。为解决这个问题,Junit 4 引入了一个新的功能参数化测试,允许开发人员使用不同的值反复运行同一个测试。参数化测试主要解决一次性进行多个测试用例的测试。其主要思想是,将多个测试用例按照,{输入值,输出值}(输入值可以是多个)的列表方式进行测试。
  要进行参数化测试,需要在类上面指定如下的运行器:@RunWith (Parameterized.class),然后,在提供数据的方法上加上一个@Parameters注解,这个方法必须是静态static的,并且返回一个集合Collection。

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.*;
import static org.junit.Assert.assertEquals;@RunWith(Parameterized.class)
public class MyJUnit4ParaTest {private int input1;private int input2;private int expected;/*** 准备数据。数据的准备需要在一个方法中进行,该方法需要满足一定的要求:* 1)该方法必须由Parameters注解修饰* 2)该方法必须为public static的* 3)该方法必须返回Collection类型* 4)该方法的名字不做要求* 5)该方法没有参数*/@Parameterized.Parameterspublic static Collection<Object[]> prepareData() {Object[][] object = {{3, 1, 4}, {36, 6, 42}, {0, 4, 4}};return Arrays.asList(object);}/*** 构造方法** 必须要为类的所有字段赋值,不管是不是都用到!否则,Junit会出错。*/public MyJUnit4ParaTest(int input1, int input2, int expected) {this.input1 = input1;this.input2 = input2;this.expected = expected;}@Testpublic void testDiv() {Calculator calc = new Calculator();// input1,input2,expected分别对应二维数组元素的第一个,第二个和第三个元素int result = calc.add(input1, input2);   assertEquals(expected, result);}
}class Calculator {public int add(int a, int b) {return a + b;}
}

  一般来说,在一个类里面只执行一个测试方法。因为所准备的数据是无法共用的,这就要求,所要测试的方法是大数据量的方法,所以才有必要写一个参数化测试。而在实际开发中,参数化测试用到的并不是特别多。

四、结语

  到这里,想必你对 JUnit 4 也有了基本的了解和掌握,都说单元测试是提升软件质量,提升研发效率的必备环节,从会用 JUnit 4 写单元测试开始,培养写测试代码的习惯,在不断实践中提升自身的开发效率,让写出来的代码有更质量的保证。


http://chatgpt.dhexx.cn/article/lQ5Qppnu.shtml

相关文章

JUnit4高级篇-由浅入深

JUnit4是JUnit框架有史以来的最大改进&#xff0c;其主要目标便是利用Java5的Annotation特性简化测试用例的编写。 先简单解释一下什么是Annotation&#xff0c;这个单词一般是翻译成元数据。元数据是什么&#xff1f;元数据就是描述数据的数据。也就是说&#xff0c;这个东西在…

Junit4Junit5对比

Junit是Java编程语言的单元测试框架&#xff0c;用来编写单元测试代码。随着Junit5的盛行&#xff0c;与Junit4有何差异。 JDK支持 Junit4需要Java5版本 Junit5需要Java8版本 Maven依赖 Junit4不区分模块&#xff0c;只有一个jar&#xff1a; <dependency><groupId>…

eclipse中Junit4(单元测试)的配置和使用

在项目的实际开发中&#xff0c;我们需要在完成每层的功能代码实现之后去对该功能的代码进行测试&#xff0c;这是因为如果在所有的代码都写完之后在测试的话&#xff0c;会造成调试困难&#xff0c;代码修改起来也很繁琐&#xff0c;这样开发效率会大大降低&#xff0c;不利于…

IDEA中添加junit4的三种方法

1、第一种方法 首先创建一个工程&#xff0c;创建好一个测试类&#xff0c;类的名称最好不要取Test&#xff0c;接下来写下一个注解Test&#xff0c;此时会报错。 报错的原因是创建的工程项目没有导入Junit4依赖&#xff0c;具体查看是在左上角 file–>project structure …

JUnit 4 与 TestNG 对比

Junit 4 和 TestNG 都是 Java 方面非常流行的单元测试框架。在功能上两个框架都非常类似。到底哪个比较好&#xff1f;在Java项目中我们应该选择哪个框架&#xff1f; 下图将会对Junit 4 和 TestNG 做个功能特征的对比。 注解支持 Junit 4 和 TestNG 在注解方面的实现非常相似。…

Junit 4 Tutorials(Junit 4 教程) 一、Junit简介及Junit Eclipse 教程

Junit 测试框架简介 测试框架是最流行的Java单元测试框架。Junit被用来开发对Java类的单元测试。它就是一个类包&#xff0c;提供了各种方法来测试Java类中的方法(method)。 Junit 4 特性 简单的注解&#xff0c;提供书写Junit测试的基本特性断言方法(Assert Methods)比较测试…

JUnit4 与 JUnit 5 常用注解对比

JUnit4 与 JUnit 5 常用注解对比 JUnit4JUnit5说明TestTest表示该方法是一个测试方法。JUnit5与JUnit 4的Test注解不同的是&#xff0c;它没有声明任何属性&#xff0c;因为JUnit Jupiter中的测试扩展是基于它们自己的专用注解来完成的。这样的方法会被继承&#xff0c;除非它…

JUnit4教程(一):基本应用

一、简介 这个估计大家都比我清楚了&#xff0c;JUnit是一个单元测试框架&#xff0c;我们可以基于它编写用来测试代码的代码&#xff0c;从而更方便地进行回归测试。 二、编写测试与断言&#xff08;Assertion&#xff09; 在Junit4中&#xff0c;编写一个测试方法只需要使用…

JUnit4使用教程-快速入门

序言 大学刚学java的时候就听说过JUnit了&#xff0c;单元测试框架&#xff0c;很好用的测试框架&#xff0c;JUnit测试框架将测试更加便捷和容易&#xff0c;编写测试代码也是简单、明了&#xff0c;功能强大。今天我给大家简单分享一下最新JUnit4的使用&#xff0c;几分钟入…

单元测试——junit4入门例子

简单的Junit4 单元测试入门例子 新建第一个测试test case 这次我使用一个简单的例子来介绍如何写一个简单的单元测试&#xff0c;这里所用的测试工具是eclipse。 点击下载->涉及的项目源代码下载 被测文件 Calculate.java package com.junit4.main;public class Calcul…

JUnit4教程

因jdk5中的新特性&#xff0c;JUnit4也因此有了很大的改变。确切的说&#xff0c;Junit4简直就不是3的扩展版本&#xff0c;而是一个全新的测试框架。下面详细介绍JUnit4的使用方法 1.测试方法&#xff1a; 在junit4之前&#xff0c;测试类通过继承TestCase类&#xff0c;并使用…

JUnit4 jar包下载

JUnit4 jar包 链接&#xff1a;https://pan.baidu.com/s/112B-PaQvlTAzEXxHcpC9Sw 密码&#xff1a;ktrn

JUnit4单元测试入门教程

JUnit4单元测试入门教程 - 简书 本文按以下顺序讲解JUnit4的使用 下载jar包单元测试初体验自动生成测试类执行顺序Test的属性 下载jar包## 下载地址 在github上&#xff0c;把以下两个jar包都下载下来。 下载junit-4.12.jar&#xff0c;junit-4.12-javadoc.jar&#xff08;文…

JUnit4的使用和配置

JUnit4是JUnit框架有史以来的最大改进&#xff0c;其主要目标便是利用Java5的Annotation特性简化测试用例的编写。 先简单解释一下什么是Annotation&#xff0c;这个单词一般是翻译成元数据。元数据是什么&#xff1f;元数据就是描述数据的数据。也就是说&#xff0c;这个东西在…

浅谈java单元测试框架junit4/5

0 前言 junit是一个开源的Java语言的单元测试框架。目前junit主要有版本junit3&#xff0c;junit4和junit5。因在junit3中&#xff0c;是通过对测试类和测试方法的命名来确定是否是测试&#xff0c;且所有的测试类必须继承junit的测试基类TestCase&#xff0c;所以本文不再讨论…

IDEA中使用JUnit4(单元测试框架)超详细!

IDEA中使用JUnit4教程 超详细&#xff01;(单元测试框架) 导语&#xff1a;自动化测试的必经之路–Selenium 作者&#xff1a;变优秀的小白 Github&#xff1a;YX-XiaoBai QQ交流群(new): 811792998 爱好&#xff1a;Americano More Ice ! 话不多说&#xff0c;实战为主&…

Junit 4 的使用

一、什么是 Junit 我们来百度一波&#xff0c;什么是 Junit 可以看到哈&#xff0c;Junit 是一个 Java 语言的单元测试框架&#xff0c;这个东西是程序员自测所需要的一个东西&#xff0c;这个测试也被称为白盒测试。&#xff08;下面会去说什么是白盒测试&#xff09; 我们之…

JUnit4

1.JUnit4全面引入Annotation来执行我们编写的测试 2.JUnit4并不要求测试类继承TestCase父类 3.在一个测试类中&#xff0c;所有被Test注解所修饰的public,void方法都是test case,可以被JUnit所执行。 4.虽然JUnit4并不要求测试方法名以test开头&#xff0c;但我们最好还是按照 …

Junit 4详解

Java单元机测试框架 --- Junit4 1、什么是Junit4 JUnit4是一个易学易用的Java单元测试框架,一般我们在写完一段代码或一个方法的时候,都要测试一下这段代码和这个方法的逻辑是不是正确,输入一定的数据,返回的数据是不是我们想要的结果,即我们在写单个业务代码针对结果进行…

IOS UIBUtton

Type 第二个是Customer 常用 按钮的阴影效果只能左右 这是区别于标签的地方 阴影设置没有负值 按钮的代码使用 按钮点击方法 代码设置 传参