Java单元测试浅析(JUnit+Mockito)

这篇具有很好参考价值的文章主要介绍了Java单元测试浅析(JUnit+Mockito)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Java测试我们应该都遇到过,一般我们会被要求做单元测试,来验证我们代码的功能以及效率。

这里来和大家一起探讨下有关单于测试。

什么是单元测试?

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

经常与单元测试联系起来的另外一些开发活动包括代码走读(Code review),静态分析(Static analysis)和动态分析(Dynamic analysis)。静态分析就是对软件的源代码进行研读,查找错误或收集一些度量数据,并不需要对代码进行编译和执行。动态分析就是通过观察软件运行时的动作,来提供执行跟踪,时间分析,以及测试覆盖度方面的信息。

单元测试的必要性?

公司要求我们写单元测试,我们会按照公司要求的单元测试率,来进行相关工作的完成;

那么会出现这样一些情况:

  • 感觉写单元测试费力不讨好,有时候写单元测试的时间大于写业务逻辑的时间,需要 mock 一大堆数据。要保证各种覆盖率,特别是分支覆盖率,需要覆盖到所写的每一个分支。
  • 大家写的单元测试质量参差不齐,因为感觉大家都是为了写测试而写测试,而不是真正的 tdd 
  • 迭代频繁,节奏紧凑的环境下,想要做到真正的 tdd ,还是有很大的难度的

确实,这是一个比较常见的问题。

那么我觉得,对于公司而言,需要有一套相关的单元测试规范,哪些是必须要去写单元测试的,分高低的优先级。同时对于单元测试案例,要做到及时的审查,关注其覆盖率,关注其有效性,对于无效的测试要及时剔除和优化。

单元测试的意义

程序代码都是由基本单元不断组合成复杂的系统,底层基本单元都无法保证输入输出正确性,层级递增时,问题就会不断放大,直到整个系统崩溃无法使用。所以单元测试的意义就在于保证基本功能是正常可用且稳定的。而对于接口、数据源等原因造成的不稳定因素,是外在原因,不在单元测试考虑范围之内。

JUnit使用

Controller层单元测试

这里我们以Springboot为例:

1、引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

2、代码案例

@RunWith(SpringRunner.class)
@SpringBootTest(classes = MainApplication.class)
public class StudentControllerTest {
	
	// 注入Spring容器
    @Autowired
    private WebApplicationContext applicationContext;
    // 模拟Http请求
    private MockMvc mockMvc;

    @Before
    public void setupMockMvc(){
    	// 初始化MockMvc对象
        mockMvc = MockMvcBuilders.webAppContextSetup(applicationContext).build();
    }
    
    /**
     * 新增学生测试用例
     * @throws Exception
     */
    @Test
    public void addStudent() throws Exception{
        String json="{"name":"张三","className":"三年级一班","age":"20","sex":"男"}";
        mockMvc.perform(MockMvcRequestBuilders.post("/student/save")    //构造一个post请求
                    // 发送端和接收端数据格式
                    .contentType(MediaType.APPLICATION_JSON_UTF8)
                    .accept(MediaType.APPLICATION_JSON_UTF8)
                    .content(json.getBytes())
            )
           // 断言校验返回的code编码
           .andExpect(MockMvcResultMatchers.status().isOk())
           // 添加处理器打印返回结果
           .andDo(MockMvcResultHandlers.print());
    }
}

只需要在类或者指定方法上右键执行即可,可以直接充当 postman 工作访问指定 url,且不需要写请求代码,

本案例中构造 mockMVC 对象时,也可以使用如下方式:

@Autowired
private StudentController studentController;
@Before
public void setupMockMvc(){
   // 初始化MockMvc对象
   mockMvc = MockMvcBuilders.standaloneSetup(studentController).build();
}

其中 MockMVC 是 Spring 测试框架提供的用于 REST 请求的工具,是对 Http 请求的模拟,无需启动整个模块就可以对 Controller 层进行调用,速度快且不依赖网络环境。

使用 MockMVC 的基本步骤如下:

  1. mockMvc.perform 执行请求

  2. MockMvcRequestBuilders.post 或 get 构造请求

  3. MockHttpServletRequestBuilder.param 或 content 添加请求参数

  4. MockMvcRequestBuilders.contentType 添加请求类型

  5. MockMvcRequestBuilders.accept 添加响应类型

  6. ResultActions.andExpect 添加结果断言

  7. ResultActions.andDo 添加返回结果后置处理

  8. ResultActions.andReturn 执行完成后返回相应结果

Service层单元测试

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

	@Autowired
    private StudentService studentService;

    @Test
    public void getOne() throws Exception {
    	 Student stu = studentService.selectByKey(5);
         Assert.assertThat(stu.getName(),CoreMatchers.is("张三"));
    }
}

执行结果

Java单元测试浅析(JUnit+Mockito)

DAO层单元测试

代码示例

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

	@Autowired
    private StudentMapper studentMapper;

    @Test
    @Rollback(value = true)
    @Transactional
    public void insertOne() throws Exception {
    	 Student student = new Student();
    	 student.setName("李四");
    	 student.setMajor("计算机学院");
    	 student.setAge(25);
    	 student.setSex('男');
    	 int count = studentMapper.insert(student);
    	 Assert.assertEquals(1, count);
    }
}

 Java单元测试浅析(JUnit+Mockito)

 其中 @Rollback (value = true) 可以执行单元测试之后回滚所新增的数据,保持数据库不产生脏数据。

异常测试

1、首先我们在service层可以定义一个异常情况

public void computeScore() {
   int a = 10, b = 0;
   int c = a/b;
}

2、我们在service中编写单元测试

@Test(expected = ArithmeticException.class)
    public void computeScoreTest() {
        studentService.computeScore();
    }

执行单元测试也会通过,原因是 @Test 注解中的定义了异常

Java单元测试浅析(JUnit+Mockito)

 查看单元测试的覆盖率

1) 单测覆盖率

测试覆盖率是衡量测试过程工作本身的有效性,提升测试效率和减少程序 bug,提升产品可靠性与稳定性的指标。

统计单元测试覆盖率的意义:

1) 可以洞察整个代码中的基础组件功能的所有盲点,发现相关问题。

2) 提高代码质量,通常覆盖率低表示代码质量也不会太高,因为单测不通过本来就映射出考虑到各种情况不够充分。

3) 从覆盖率的达标上可以提高代码的设计能力。

(2) 在 idea 中查看单元测试覆盖率很简单,只需按照图中示例的图标运行,或者在单元测试方法或类上右键 Run 'xxx' with Coverage 即可。执行结果是一个表格,列出了类、方法、行数、分支覆盖情况。

Java单元测试浅析(JUnit+Mockito)

(3) 在代码中会标识出覆盖情况,绿色的是已覆盖的,红色的是未覆盖的。

Java单元测试浅析(JUnit+Mockito)

(4) 如果想要导出单元测试的覆盖率结果,可以使用如下图所示的方式,勾选 Open generated HTML in browser

Java单元测试浅析(JUnit+Mockito)

 文章来源地址https://www.toymoban.com/news/detail-461432.html

导出结果:

Java单元测试浅析(JUnit+Mockito)

 

JUnit插件自动生成测试案例

1) 安装插件,重启 idea 生效

Java单元测试浅析(JUnit+Mockito)

(2) 配置插件

Java单元测试浅析(JUnit+Mockito)

 

(3) 使用插件

在需要生成单测代码的类上右键 generate...,如下图所示。

Java单元测试浅析(JUnit+Mockito)

生成结果:

Java单元测试浅析(JUnit+Mockito)

单元测试工具Mockito

简介

Mockito 是一个针对 Java 的 mocking 框架。它与 EasyMock 和 jMock 很相似,但是通过在执行校验什么已经被调用,它消除了对期望行为(expectations)的需要。其它的 mocking 库需要你在执行记录期望行为(expectations),而这导致了丑陋的初始化代码。

Mock 过程的使用前提:

(1) 实际对象时很难被构造出来的

(2) 实际对象的特定行为很难被触发

(3) 实际对象可能当前还不存在,比如依赖的接口还没有开发完成等等。

Mockito 官网:https://site.mockito.org 。Mockito 和 JUnit 一样是专门针对 Java 语言的 mock 数据框架,它与同类的 EasyMock 和 jMock 功能非常相似,但是该工具更加简单易用。

Mockito 的特点:

(1) 可以模拟类不仅仅是接口

(2) 通过注解方式简单易懂

(3) 支持顺序验证

(4) 具备参数匹配器

使用案例

1、在之前的代码中在定义一个 BookService 接口,含义是借书接口,暂且不做实现

public interface BookService {
    Book orderBook(String name);
}

2、在之前的 StudentService 类中新增一个 orderBook 方法,含义是学生预定书籍方法,其中实现内容调用上述的 BookService 的 orderBook 方法。

public Book orderBook(String name) {
   return bookService.orderBook(name);
}

 3、编写单元测试方法,测试 StudentService 的 orderBook 方法

@Test
public void orderBookTest() {
    Book expectBook = new Book(1L, "钢铁是怎样炼成的", "书架A01");
    Mockito.when(bookService.orderBook(any(String.class))).thenReturn(expectBook);
    Book book = studentService.orderBook("");
    System.out.println(book);
    Assert.assertTrue("预定书籍不符", expectBook.equals(book));
}

4、执行结果

Java单元测试浅析(JUnit+Mockito)

 

上述内容并没有实现 BookService 接口的 orderBook (String name) 方法。但是使用 mockito 进行模拟数据之后,却通过了单元测试,原因就在于 Mockito 替换了本来要在 StudentService 的 orderBook 方法中获取的对象,此处就模拟了该对象很难获取或当前无法获取到,用模拟数据进行替代。

Java单元测试浅析(JUnit+Mockito)

 

到了这里,关于Java单元测试浅析(JUnit+Mockito)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 单元测试编写最佳实践(ChatGPT+Mockito+JUnit)

    基于 springboot 微服务架构给单元测试带来的问题: springboot 单元测试启动家长过程非常缓慢,后期服务启动达到分钟级,非常影响效率 服务之间相互依赖非常严重,单元测试的运行非常依赖其它服务稳定性 第三方服务和中间件,测试过程产生大量垃圾数据,污染环境,非常

    2024年02月09日
    浏览(45)
  • SpringBoot单元测试--Mockito+Junit5框架使用

    作为程序员为了提前发现代码bug,优化代码; 通常我们写完某个功能模块代码后都需要写单元测试对代码块进行测试(特别是敏捷开发中);Java项目最常用的单元测试框架即为Junit(目前最新版本为Junit5),SpringBoot本身也整合了该框架。在写单元测试时代码块中的调到第三方接口方

    2024年02月02日
    浏览(45)
  • SpringBoot 实战:JUnit5+MockMvc+Mockito 做好单元测试

    因为继承了 spring-boot-starter-parent ,所以我们依赖的 spring-boot-starter-test 不需要写具体的版本,可以直接集成父级的版本定义。其中, spring-boot-starter-web 是用于提供 REST API 的 web 容器, spring-boot-starter-test 可以提供各种测试框架的, spring-boot-maven-plugin 是将 SpringBoot 应用打包为

    2024年04月15日
    浏览(52)
  • 深度揭秘JUnit5与Mockito的单元测试神秘面纱

    在今天的学习中,我们将深入研究 JUnit 和Mockito,这是 Java 开发中最强大的 单元测试 工具之一。通过学习如何编写清晰、高效的单元测试,我们将揭开单元测试的神秘面纱,助力你在项目中写出更健壮的代码。 提示: 今天的代码是在第九天代码的基础上进行开发,我们将为

    2024年02月02日
    浏览(53)
  • Spring Boot使用JUnit和Mockito进行Service层单元测试

      在平时的开发当中,一个项目往往包含了大量的方法,可能有成千上万个。如何去保证这些方法产生的结果是我们想要的呢?那么在SpringBoot项目中我们是如何对Service层的方法进行测试的呢?   单元测试是一种软件测试方法,用于测试代码的最小可测试单元。在Java开发

    2024年02月03日
    浏览(52)
  • Spring Boot与微服务测试:JUnit和Mockito的单元和集成测试实践

    微服务架构的流行使得测试变得更为重要。在Spring Boot应用中,使用JUnit和Mockito进行单元和集成测试是一种常见的实践。本文将深入探讨如何利用这两个测试框架,确保Spring Boot微服务的可靠性和稳定性。 单元测试 1.1 JUnit简介 JUnit是Java中最为流行的单元测试框架之一,它提供

    2024年02月21日
    浏览(50)
  • 基于Junit4+Mockito+PowerMock实现Controller+Service的单元测试

    一 导入的依赖 二 依赖版本 三 controller测试示例代码       controller         controllerTest         测试结果:覆盖率100%         带异常的Controller         带异常提示的ControllerTest         测试结果,覆盖率100%   三 service测试示例代码         service         serviceTest    

    2024年02月14日
    浏览(43)
  • spring boot 单元测试JUnit5使用Mockito模拟Mock数据调用

    spring boot 单元测试JUnit5使用Mockito模拟Mock数据调用 好大一批新用法,大家静下心来好好看看吧 1. spring boot 使用 Mockito.when().thenReturn()模拟返回值 Mockito 是一种 Java mock 框架,他主要就是用来做 mock 测试的,他可以模拟任何 Spring 管理的 bean、模拟方法的返回值、模拟抛出异常…

    2024年02月15日
    浏览(55)
  • springboot项目使用Junit5 + mockito + jacoco 实现单元测试以及代码覆盖率检查

    在创建springboot项目时会默认添加spring-boot-starter-test依赖,其中已经包含了junit、mockito依赖,根据springboot版本的不同junit和mockito的版本也会有所不同 先说一下各自功能: junit只说一点,junt4和junit5的注解不同,使用方式略有差异,其他不赘述了,基本用法都懂。 mockito是mock的

    2023年04月23日
    浏览(55)
  • mockito+junit 单元测试 测试私有方法利用反射去调用提升覆盖率 反射调用时传入参数为 null

    今天公司安排我写单元测试 因为要通过三级认证 公司要求是覆盖率必须达到100% 而在写单元测试的时候 对于是否要测试私有方法一直是一个争议 公司规范 对私有方法也进行测试 代码如下: JudgeUtils 是公司封装的一个工具类 让我们看看 isNull 方法的内部 代码如下: 我现在需

    2024年02月11日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包