JUnit单元测试

2023-11-10

介绍

JUnit是一种Java语言的单元测试框架,它是最流行的单元测试框架之一。它提供了一些可用于编写和运行测试的API,并且可以生成测试报告。JUnit适用于所有Java语言的项目,例如Java应用程序、Java Servlet、Java EE应用程序以及Android应用程序等。

依赖

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>

RunWith

Springboot集成JUnit写单元测试类需要使用RunWith注解,这个注解需要一个值,测试运行器。
测试运行器(Test Runner)是JUnit框架提供的一个核心组件,用于执行测试类中的测试方法并生成测试报告。JUnit提供了多个测试运行器,不同的运行器可以根据不同的需求来选择使用。

  • JUnit4:JUnit4是JUnit框架的主流版本,支持使用注解方式进行测试。我们一般会选择使用@RunWith(JUnit4.class)运行器来执行测试用例。
  • SpringRunner:SpringRunner是Spring Boot Test框架中提供的测试运行器,用于执行集成测试和端到端测试等。可以使用@RunWith(SpringRunner.class)运行器来启动Spring Boot上下文环境,并进行测试。
  • Parameterized:Parameterized是JUnit提供的一个参数化测试运行器,可以让我们在单元测试中重复运行相同的测试方法,并对方法参数进行变量化处理。
  • Theories:Theories是JUnit提供的一个更加高级的参数化测试运行器,可以生成随机数据、枚举值、自定义输入等多种方式来测试方法的正确性。
  • Suite:Suite运行器可以将多个测试类组合成一组测试用例,方便批量执行和管理测试用例。

Assert类

Assert是JUnit框架提供的一个断言类,用于验证测试结果和预期结果是否相符。我们可以使用Assert类来编写断言代码,从而保证测试的正确性和可靠性。

  • assertEquals(expected, actual):验证两个值是否相等,如果不相等则抛出AssertionError异常。
  • assertNotEquals(expected, actual):验证两个值是否不相等,如果相等则抛出AssertionError异常。
  • assertTrue(condition):验证给定的条件是否为true,如果不是则抛出AssertionError异常。
  • assertFalse(condition):验证给定的条件是否为false,如果不是则抛出AssertionError异常。
  • assertNull(object):验证给定对象是否为空(null),如果不为空则抛出AssertionError异常。
  • assertNotNull(object):验证给定对象是否不为空(null),如果为空则抛出AssertionError异常。
  • assertArrayEquals(expected, actual):验证两个数组是否相等,如果不相等则抛出AssertionError异常。
  • assertSame(expected, actual):验证两个对象是否相等,如果不相等则抛出AssertionError异常。
  • assertNotSame(notExpected, actual):验证两个对象是否不相等,如果相等则抛出AssertionError异常。

断言方法的第一个参数通常是预期值(expected),而第二个参数则是实际值(actual)。

JUnit的注解

  • @Test:这是JUnit最重要的注解之一,它被用来标记测试方法。JUnit会执行所有带有@Test注解的方法,以验证代码的正确性。
  • @Before:在每个测试方法执行之前该注解所标注的方法会被执行。通常,这个注解可以用于初始化测试数据和资源。
  • @After:在每个测试方法执行之后该注解所标注的方法会被执行。通常,这个注解可以用于清理测试数据和资源。
  • @BeforeClass:在整个测试类中只执行一次,在执行测试用例之前该注解所标注的方法会被执行,且这个方法必须是静态方法,也就是这个方法会在类加载时执行。通常,这个注解可以用于初始化静态数据和资源。
  • @AfterClass:在整个测试类中只执行一次,在执行测试用例之后该注解所标注的方法会被执行,同样,这个方法必须是静态方法。通常,这个注解可以用于清理静态数据和资源。
  • @Ignore:该注解表示忽略某个测试方法,不会执行该方法。通常,这个注解可以用于临时禁用某个测试用例。
  • @RunWith:该注解定义测试运行器,JUnit默认使用BlockJUnit4ClassRunner作为测试运行器。如果需要使用其他运行器,可以在注解中指定。
  • @Parameters:该注解可以用于动态参数化测试方法,使测试方法能够接受不同的输入参数。
  • @Rule:该注解定义测试规则(Test Rule),可以在测试方法执行前后实施某些操作,如超时控制、异常检测等。
  • @ClassRule:类似于@Rule,但是粒度更大,可以对整个测试类进行规则控制。

使用@Test可能遇见的问题:
不能加载通过@Autowired注解引入的Spring bean
org.junit的Test不能使用spring的bean而org.junit.jupiter.api的Test可以

org.junit.jupiter.api.Test
org.junit.Test

org.junit的Test和org.junit.jupiter.api的Test注解本质上并没有限制能否使用spring的bean,但是它们对于test执行时的上下文环境有所不同。
在JUnit 4中(org.junit.Test),测试类是由JUnit框架进行实例化。当使用JUnit 4的@Test注解时,测试类的实例是由JUnit框架直接创建的,而不是由Spring容器创建的。因此,如果您试图在JUnit 4测试中使用spring bean,就需要手动创建bean并注入到测试类中,或将bean作为参数传递给测试方法。
而在JUnit 5中(org.junit.jupiter.api.Test),测试实例可以由Spring容器创建。JUnit 5引入了@SpringBootTest注解,该注解用于启用Spring的上下文,将测试实例化为Spring bean,并允许使用@Autowired注解来注入其他Spring bean。这样,测试实例就可以使用Spring应用程序上下文中的任何bean和服务,包括JdbcTemplate等。

Parameters

该注解用于动态参数化测试方法,允许为每个测试运行提供不同的输入参数。

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Arrays;
import java.util.Collection;
import static org.junit.Assert.assertEquals;


@SpringBootTest
@RunWith(Parameterized.class)
public class JunitTest {

    @Parameterized.Parameters
    public static Collection<Object[]> data() {
        return Arrays.asList(new Object[][]{{1, 2}, {3, 4}, {5, 6}});
    }

    private int input;
    private int expected;

    public JunitTest(int input, int expected) {
        this.input = input;
        this.expected = expected;
    }

    @Test
    public void test() {
        assertEquals(expected, input + 1);
    }
}

在这个例子中,我们有一个JunitTest 类,它有一个带有两个参数的构造函数。为了测试JunitTest 类的行为是否正确,我们使用JUnit的@Parameters注解来动态生成多组输入参数,并分别对每个参数运行测试方法。每组参数由一个长度为2的Object数组表示,第一个元素代表输入值,第二个元素代表期望输出值。
在JUnit中,@RunWith(Parameterized.class)注解指定了JUnit要使用参数化测试运行器来运行测试方法。@Parameters注解用于指定参数集合,该示例中,我们返回了一个数组列表,其中每个元素都是长度为2的Object数组,表示要测试的输入和期望输出值。
在这个示例中,我们测试了三个参数组,并分别检查它们的输出是否正确。

Rule

import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.Timeout;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;


@SpringBootTest
@RunWith(SpringRunner.class)
public class JunitTest {

    @Rule
    public Timeout globalTimeout = Timeout.seconds(10);

    @Test
    public void test() {
        try {
            Thread.sleep(15000); //org.junit.runners.model.TestTimedOutException: test timed out after 10 seconds
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        Assert.assertEquals(5, 5);
    }
}

测试规则

除了上面的超时还有:

ExpectedException 规则

ExpectedException 规则可以验证预期的异常是否被抛出,并检查异常消息和类型是否正确。它通常用于测试方法在给定错误输入时是否正确地抛出异常。

public class MyTest {
    @Rule
    public ExpectedException exception = ExpectedException.none();

    @Test
    public void test() {
        exception.expect(IOException.class);
        exception.expectMessage("File not found");
        // some code that throws an IOException with message "File not found"
    }
}

test方法抛出的异常和exception期待的异常及异常message相同则测试成功

TemporaryFolder 规则

TemporaryFolder 规则可以创建临时目录和临时文件,以便在测试中保存数据和状态。它通常用于模拟测试环境和确保测试数据不会影响程序的实际运行环境。

public class MyTest {
    @Rule
    public TemporaryFolder folder = new TemporaryFolder();

    @Test
    public void test() throws IOException {
        File file = folder.newFile("test.txt");
        assertTrue(file.exists());
    }
}

在这个例子中,我们定义了一个 TemporaryFolder 规则,然后在测试方法中使用 newFile() 方法来创建一个新文件。TemporaryFolder 规则会自动清理临时文件和目录,以确保测试不会影响到实际文件系统。

Stopwatch 规则

Stopwatch 规则可以测量测试方法的运行时间,并检查是否超过了预定的时间阈值。它通常用于确保测试方法在合理的时间内完成,避免测试用例过于耗时或死循环等问题。

public class MyTest {
    @Rule
    public Stopwatch stopwatch = new Stopwatch() {
        @Override
        protected void succeeded(long nanos, Description description) {
            assertTrue(nanos < TimeUnit.SECONDS.toNanos(1));
        }
    };

    @Test
    public void test() throws InterruptedException {
        Thread.sleep(900);
    }
}

在这个例子中,我们定义了一个 Stopwatch 规则,并覆盖了其 succeeded() 方法来检查测试方法是否在1秒内完成。如果测试方法过于耗时,则测试失败。

TestName 规则

TestName 规则可以获取当前测试方法的名称,并将其保存到一个 String 类型的变量中。它通常用于将测试方法的名称与输出结果关联起来,以便更好地了解测试方法的行为和结果。

public class MyTest {
    @Rule
    public TestName testName = new TestName();

    @Test
    public void test() {
        System.out.println(testName.getMethodName());
        // output: test
    }
}

在这个例子中,我们定义了一个 TestName 规则,并在测试方法中使用 getMethodName() 方法来获取当前测试方法的名称。我们使用 System.out.println() 将测试方法的名称输出到控制台。

ExternalResource 规则

ExternalResource 规则可以在测试方法执行前创建资源,并在方法执行完毕后清理资源。它通常用于模拟外部资源,如数据库连接、网络连接等。

public class MyTest {
    @Rule
    public ExternalResource resource = new ExternalResource() {
        private ResourceObject resource;

        @Override
        protected void before() throws Throwable {
            resource = new ResourceObject();
            resource.connect();
        }

        @Override
        protected void after() {
            resource.disconnect();
        }
    };

    @Test
    public void test() {
        // some code that uses the resource object
    }
}

在这个例子中,我们定义了一个 ExternalResource 规则,并覆盖了其 before() 和 after() 方法来创建和清理资源。在测试方法中,我们可以使用创建好的资源对象执行测试。

ErrorCollector 规则

ErrorCollector 规则可以收集测试过程中发生的所有错误,并在测试结束时一次性输出错误消息。它通常用于测试方法涉及多个步骤或条件,其中任何一个步骤或条件失败都会导致整个测试失败。

public class MyTest {
    @Rule
    public ErrorCollector collector = new ErrorCollector();

    @Test
    public void test() {
        int result1 = someMethod();
        collector.checkThat(result1, equalTo(10));

        int result2 = someOtherMethod();
        collector.checkThat(result2, equalTo(20));

        // some more code that may throw exceptions or fail assertions
    }
}

在这个例子中,我们定义了一个 ErrorCollector 规则,并在测试方法中使用 checkThat() 方法来检查每个步骤的结果是否符合预期。如果任何一个步骤失败,则该测试失败,并且所有错误消息都会在测试结束时输出。

ClassRule

该注解与@Rule类似,但是它作用于整个测试类而不是每个测试方法。

例子

import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;


@SpringBootTest
@RunWith(SpringRunner.class)
public class JunitTest {

    @BeforeClass
    public static void beforeClass() {
        System.out.println("beforeClass");
    }

    @Before
    public void before() {
        System.out.println("before");
    }

    @Test
    public void test() {
        int actual = 5;
        Assert.assertEquals(5, actual);
        System.out.println("test");
    }

    @Test
    public void test1() {
        int actual = 8;
        Assert.assertEquals(8, actual);
        System.out.println("test1");
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JUnit单元测试 的相关文章

随机推荐

  • jupyter notebook使用基础及其快捷键,包括对文档操作、cell操作、快捷键、markdown

    目录 Jupyter Notebook介绍 使用原因 基本操作 新建notebook文档 对文档的操作 cell操作 什么是cell Jupyter支持两种模式 鼠标操作 Jupyter快捷键操作 markdown演示 手动建导航 Jupy
  • 网络编程 - Java SSLSocketFactory 创建方式

    SSL TLS 认证需要服务端提供 KeyStore jks TrustStore jks 实现方式 优缺点 服务端提供 CA Client CRT Client Key 文件 缺点 服务端提供原始签名 不安全不建议采用 服务端提供 Key
  • linux $0命令,Linux:awk命令详解

    简单使用 awk 对于文件中一行行的独处来执行操作 awk F print 1 4 使用 来分割这一行 把这一行的第一第四个域打印出来 AWK命令介绍 awk语言的最基本功能是在文件或字符串中基于指定规则浏览和抽取信息 awk抽取信息后 才
  • 2023最新pycharm详细安装教程,小白必看

    一 python官网 Python官网主要有python的About 简介 Downloads 下载 Documentation 文档 Community 团体 Success Stories 成功案例 News 新闻 Events 事件动
  • 贪吃蛇智能版(专家)

    在高级版本的基础之上 主要针对以下问题进行了处理 当长度逐渐变成 超过100之后 随机wander 追尾有比较大的随机性 弄不好就把自己围死了 这个时候已经不能再看到实物马上就去吃了 在吃之前必须先调整好自身的状态 等到认为调整的差不多的时
  • 如何在sqlserver建立新用户并关联相应的数据库

    我们经常需要在数据库上建立有权限的用户 该用户只能去操作某个特定的数据库 比如该用户只能去读 去写等等 那么我们应该怎么在sqlserver上设置呢 下面的步骤有点长 只要一步一步跟着设置就行 方法 步骤 如果你没有开通sqlserver身
  • GoWeb开发-3.JWT

    1 导入依赖库 go get u github com dgrijalva jwt go 2 生成token import fmt github com gin gonic gin jwt github com dgrijalva jwt
  • 将树莓派上的文件发送到服务器,怎样将树莓派变成网络文件系统版本4服务器...

    简介 网络文件系统 NFS 可以同时在版本2 3 4中运行 NFS版本4 NFSv4 在NFSv2和NFSv3 我最喜欢的改进是 NFSv4使配置防火墙变得简单 因为NFSv4仅使用一个端口 默认为2049 而NFSv2和NFSv3使用4个
  • 搭建 llvm 学习环境

    1 下载llvm git clone https github com llvm llvm project git 因为国内网络的原因 clone的时候没有反应 可以多此 Ctrl C 重新 clone 2 下载安装cmake 注意 下载的
  • 毕业设计-基于学习元的双螺旋深度学习模型

    目录 前言 课题背景和意义 实现技术思路 一 基于学习元的深度学习支撑系统 二 双螺旋深度学习模型 三 深度学习的开放课程设计实践 实现效果图样例 最后 前言 大四是整个大学期间最忙碌的时光 一边要忙着备考或实习为毕业后面临的就业升学做准备
  • 网页打开摄像头_听说,考试的时候你打不开摄像头?

    近期真没什么可写的 赶在考试之前就来说一说雨课堂打不开摄像头如何解决吧 先推荐一个检测浏览器摄像头权限的网址 https assistant ceping com qrcode type 1 lng zh 如果在这个网址下摄像头一切正常 雨
  • uplift model增益模型相关术语概念名词汇总

    因果推断 增益模型综述 http proceedings mlr press v67 gutierrez17a gutierrez17a pdf 名词 缩写 英文全称 名词解释 备注 treatment 干预 实验组 control 不干预
  • vscode代码发送至微信开发者工具无法识别mqtt服务器地址(无论正确服务器地址还是错误地址,均不报错也不连接)

    调试器可以正常显示报错 并且小程序界面一也可以更新UI 但是唯独不更新服务器部分的错误 未搜索到相似问题 个人尝试出了一个解决办法 解决了我个人的这个问题 不一定普适 供参考 卸载mqtt npm uninstall mqtt 安装2 18
  • gradle:Connection timed out 问题解决

    gradle Connection timed out 问题解决 gradle Connection timed out 问题解决 先来重现一下问题 公司技术选型使用了gradle作为构建工具 问题重现 使用的系统是windows10 准备
  • fgets函数使用

    一 作用 fgets函数用于从指定的文件流中读取一行字符串 并将其存储到指定的字符数组中 它可以读取包括空格在内的所有字符 直到遇到换行符或文件结束符为止 fgets函数还可以指定最大读取的字符数 以防止缓冲区溢出 二 使用方法 fgets
  • HJ17 坐标移动

    Powered by NEFU AB IN Link 文章目录 HJ17 坐标移动 题意 思路 代码 HJ17 坐标移动 题意 开发一个坐标计算工具 A表示向左移动 D表示向右移动 W表示向上移动 S表示向下移动 从 0 0 点开始移动 从
  • 26、【链表】相交链表(C++版本)

    题目描述 题目分析 目标是找到两个链表若相交时的公共结点 那么便需要分析公共结点所具有的特性 假设链表A和链表B具有公共结点 那么在公共结点处之后 两个链表具有相同长度和数值的结点 而在公共结点之前 两个链表的所具有的结点个数并不一定相等
  • 网络请求【小程序】

    一 get 二 post 1 获取相应数据 Page 页面的初始数据 data inptValue isArr 生命周期函数 监听页面加载 onLoad options onSubmit console log this data inpt
  • Unity中的序列化数据丢失

    问题描述 近期在项目制作中 需要运用Asset进行数据结构的实例化存储和使用 在制作编辑器的过程中发现一个十分尴尬的问题 在某些情况下会发生代码修改后通过编辑器配置的某些数据会丢失 我把这种问题叫做 序列化数据丢失 因为我也不知道怎么称呼它
  • JUnit单元测试

    目录 介绍 依赖 RunWith Assert类 JUnit的注解 Parameters Rule 测试规则 ExpectedException 规则 TemporaryFolder 规则 Stopwatch 规则 TestName 规则