【单元测试】Controller、Service、Repository 层的单元测试

Controller、Service、Repository 层的单元测试

  • 1.Controller 层的单元测试
    • 1.1 创建一个用于测试的控制器
    • 1.2 编写测试
  • 2.Service 层的单元测试
    • 2.1 创建一个实体类
    • 2.2 创建服务类
    • 2.3 编写测试
  • 3.Repository

1.Controller 层的单元测试

下面通过实例演示如何在控制器中使用 MockMvc 进行单元测试。

1.1 创建一个用于测试的控制器

package com.example.demo.controller;import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class HelloController {@RequestMapping("/hello")public String hello(String name) {return "hello " + name;}
}
  • @RestController:代表这个类是 REST 风格的控制器,返回 JSON/XML 类型的数据。
  • @RequestMapping:用于配置 URL 和方法之间的映射,可用在类和方法上。用于方法上,则其路径会继承用在类的路径上。

1.2 编写测试

package com.example.demo.controller;import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;import static org.junit.Assert.*;@SpringBootTest
@RunWith(SpringRunner.class)
public class HelloControllerTest {//启用web上下文@Autowiredprivate WebApplicationContext webApplicationContext;private MockMvc mockMvc;@Beforepublic void setUp() throws Exception{//使用上下文构建mockMvcmockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();}@Testpublic void hello() throws Exception {// 得到MvcResult自定义验证// 执行请求MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/hello").contentType(MediaType.APPLICATION_JSON_UTF8)//传入参数.param("name","longzhonghua")//接收的类型.accept(MediaType.APPLICATION_JSON_UTF8))//等同于Assert.assertEquals(200,status);//判断接收到的状态是否是200.andExpect(MockMvcResultMatchers.status().isOk())//等同于 Assert.assertEquals("hello longzhonghua",content);.andExpect(MockMvcResultMatchers.content().string("hello longzhonghua")).andDo(MockMvcResultHandlers.print())//返回MvcResult.andReturn();//得到返回代码int status = mvcResult.getResponse().getStatus();//得到返回结果String content = mvcResult.getResponse().getContentAsString();//断言,判断返回代码是否正确Assert.assertEquals(200,status);//断言,判断返回的值是否正确Assert.assertEquals("hello longzhonghua",content);}
}
  • @SpringBootTest:是 Spring Boot 用于测试的注解,可指定入口类或测试环境等。
  • @RunWith(SpringRunner.class):让测试运行于 Spring 的测试环境。
  • @Test:表示一个测试单元。
  • WebApplicationContext:启用 Web 上下文,用于获取 Bean 中的内容。
  • @Before:表示在测试单元执行前执行。这里使用上下文构建 MockMvc。
  • MockMvcRequestBuilders.get:指定请求方式是 GET。一般用浏览器打开网页就是 GET 方式。

运行测试,在控制器中会输出以下结果:

MockHttpServletRequest:HTTP Method = GETRequest URI = /helloParameters = {name=[longzhonghua]}Headers = [Content-Type:"application/json;charset=UTF-8", Accept:"application/json;charset=UTF-8"]Body = nullSession Attrs = {}Handler:Type = com.example.demo.controller.HelloControllerMethod = public java.lang.String com.example.demo.controller.HelloController.hello(java.lang.String)Async:Async started = falseAsync result = nullResolved Exception:Type = nullModelAndView:View name = nullView = nullModel = nullFlashMap:Attributes = nullMockHttpServletResponse:Status = 200Error message = nullHeaders = [Content-Type:"application/json;charset=UTF-8", Content-Length:"18"]Content type = application/json;charset=UTF-8Body = hello longzhonghuaForwarded URL = nullRedirected URL = nullCookies = []

在上述结果中可以看到 访问方式路径参数访问头ModelAndViewFlashMapMockHttpServletResponse

2.Service 层的单元测试

本实例演示如何在 Service 中使用 Assert 进行单元测试。

2.1 创建一个实体类

package com.example.demo.entity;import lombok.Data;
import lombok.Getter;
import lombok.Setter;@Data
public class User {private String name;private int age;
}

2.2 创建服务类

这里用 @Service 来标注服务类,并实例化一个 User 对象。

package com.example.demo.service;import com.example.demo.entity.User;
import org.springframework.stereotype.Service;@Service
public class UserService {public User getUserInfo(){User user = new User();user.setName("pipi");user.setAge(18);return user;}
}

2.3 编写测试

编写测试用于比较实例化的实体 User 和测试预期值是否一样。

package com.example.demo.service;import com.example.demo.entity.User;
import org.junit.Assert;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;import static org.hamcrest.CoreMatchers.*;//表明要在测试环境运行,底层使用的junit测试工具
@RunWith(SpringRunner.class)
// SpringJUnit支持,由此引入Spring-Test框架支持!//启动整个spring的工程
@SpringBootTest
public class UserServiceTest {@Autowiredprivate UserService userService;@Testpublic void getUserInfo() {User user = userService.getUserInfo();//比较实际的值和用户预期的值是否一样Assert.assertEquals(18, user.getAge());Assert.assertThat(user.getName(), is("pipixia"));}
}

运行测试,结果显示出错,表示期望的值和实际的值不一样。

在这里插入图片描述

3.Repository

Repository 层主要用于对数据进行增加、删除、修改和查询操作、它相当于仓库管理员的进出货操作。

下面通过实例演示如何在 Repository 中进行单元测试,以及使用 @Transactional 注解进行回滚操作。

package com.example.demo.repository;import com.example.demo.entity.Card;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;import java.util.List;import static org.junit.Assert.*;@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class CardRepositoryTest {@Autowiredprivate CardRepository cardRepository;@Testpublic void testQuery() {// 查询操作List<Card> list = cardRepository.findAll();for (Card card : list) {System.out.println(card);}}@Testpublic void testRollBack() {// 查询操作Card card = new Card();card.setNum(3);cardRepository.save(card);//throw new RuntimeException();}
}
  • @Transactional:即回滚的意思。所有方法执行完之后哦,回滚成原来的样子。
  • testRollBack 方法:执行添加一条记录。如果开启了 @Transactional,则会在添加之后进行回滚,删除刚添加的数据,如果注释掉 @Transactional,则完成添加后不回滚。大家在测试时可以尝试去掉或添加 @Transactional 状态下的不同效果。这里的 @Transactional 放在类上,也可以加在方法上作用于方法。

运行 testQuery 测试,控制台输出如下:

在这里插入图片描述
在这里插入图片描述

运行 testRollBack 测试,并添加 @Transactional,控制台输出如下:

在这里插入图片描述

上述结果表示先添加,然后操作被立即回滚了。

在这里插入图片描述

运行 testRollBack 测试,去掉 @Transactional,控制台输出如下:

在这里插入图片描述
在这里插入图片描述

注:设置了 id 为自增键。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/37799.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

API-节点操作

学习目标&#xff1a; 掌握节点操作 学习内容&#xff1a; DOM节点查找节点增加节点删除节点 DOM节点&#xff1a; DOM树里每一个内容都称之为节点。 节点类型 元素节点所有的标签比如body、div&#xff1b;html是根节点属性节点所有的属性&#xff0c;比如href文本节点所有…

FastAPI-Cookie

fastapi-learning-notes/codes/ch01/main.py at master Relph1119/fastapi-learning-notes GitHub 1、Cookie的作用 Cookie可以充当用户认证的令牌&#xff0c;使得用户在首次登录后无需每次手动输入用户名和密码&#xff0c;即可访问受限资源&#xff0c;直到Cookie过期或…

《PyTorch计算机视觉实战》:一、二章

目录 第一章&#xff1a;人工神经网络基础 比较人工智能和传统机器学习 人工神经网络&#xff08;Artificial Neural Network&#xff0c;ANN&#xff09; 是一种受人类大脑运作方式启发而构建的监督学习算法。神经网络与人类大脑中神经元连接和激活的方式比较类似&#xff0…

GoLang语言

基础 安装Go扩展 go build 在项目目录下执行go build go run 像执行脚本文件一样执行Go代码 go install go install分为两步&#xff1a; 1、 先编译得到一个可执行文件 2、将可执行文件拷贝到GOPATH/bin Go 命令 go build :编译Go程序 go build -o "xx.exe"…

4.x86游戏实战-人物状态标志位

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 上一个内容&#xff1a;3.x86游戏实战-寄存器 人物状态标志位&#xff1a; 什么叫人物状态标志位&…

Leetcode[反转链表]

LCR 024. 反转链表 给定单链表的头节点 head &#xff0c;请反转链表&#xff0c;并返回反转后的链表的头节点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1]示例 2&#xff1a; 输入&#xff1a;head [1,2] 输出&#xff1a;[2,1]示…

Go使用Gin框架开发的Web程序部署在Linux时,无法绑定监听Ipv4端口

最近有写一部分go语言开发的程序&#xff0c;在部署程序时发现&#xff0c;程序在启动后并没有绑定ipv4的端口&#xff0c;而是直接监听绑定ipv6的端口。 当我用netstat -antup | grep 3601查找我的gin服务启动的端口占用情况的时候发现&#xff0c;我的服务直接绑定了tcp6 &a…

240629_昇思学习打卡-Day11-Vision Transformer中的self-Attention

240629_昇思学习打卡-Day11-Transformer中的self-Attention 根据昇思课程顺序来看呢&#xff0c;今儿应该看Vision Transformer图像分类这里了&#xff0c;但是大概看了一下官方api&#xff0c;发现我还是太笨了&#xff0c;看不太明白。正巧昨天学SSD的时候不是参考了太阳花的…

Linux - 札记 - W10: Warning: Changing a readonly file

Linux - 札记 - W10: Warning: Changing a readonly file 这里写目录标题 一、问题描述1. 现象2. 原因 二、解决方案 一、问题描述 1. 现象 在使用 vim 编辑文件时&#xff08;我这里是要编辑 /root/.ssh/authorized_keys&#xff09;提示&#xff1a;W10: Warning: Changing…

IOS Swift 从入门到精通:ios 连接数据库 安装 Firebase 和 Firestore

创建 Firebase 项目 导航到Firebase 控制台并创建一个新项目。为项目指定任意名称。 在这里插入图片描述 下一步,启用 Google Analytics,因为我们稍后会用到它来发送推送通知。 在这里插入图片描述 在下一个屏幕上,选择您的 Google Analytics 帐户(如果已创建)。如果没…

<电力行业> - 《第7课:发电》

1 发电的原理 电力生产的发电环节是利用电能生产设备将各种一次能源或其他形式的能转换为电能。生产电能的主要方式有火力发电、水力发电、核能发电、地热发电、风力发电、太阳能发电、潮汐能发电、生物智能发电和燃料电池发电等。 除太阳能发电的光伏电池技术和燃料电池发电…

c++ 子类继承父类

这个是子类继承父类 是否重写从父类那里继承来的函数 这个例子的路径 E盘 demo文件夹 fatherChildfunc

蓝卓出席“2024C?O大会”,探讨智能工厂建设新路径

6月29日&#xff0c;“2024C?O大会”在金华成功举办。此次大会由浙江省企业信息化促进会主办&#xff0c;与以往CIO峰会不同&#xff0c;“C?O”代表了企业数字化中的核心决策者群体&#xff0c;包括传统的CIO、CEO、CDO等。 本次大会围绕C?O、AIGC与制造业、数据价值、未来…

统计信号处理基础 习题解答11-9

一个飞行器开始于一个未知位置(, )&#xff0c;按照 以常速运动&#xff0c;其中, 分别是飞行器在x、y方向的速度分量,都是未知的。我们希望估计每一时刻, 飞行器的位置和速度。尽管初始位置(, )和速度, 都是未知的,但是它们可以看成一个随机矢量。证明能够由MMSE估计器估计为 …

React+TS前台项目实战(二十一)-- Search业务组件封装实现全局搜索

文章目录 前言一、Search组件封装1. 效果展示2. 功能分析3. 代码详细注释4. 使用方式 二、搜索结果展示组件封装1. 功能分析2. 代码详细注释 三、引用到文件&#xff0c;自行取用总结 前言 今天&#xff0c;我们来封装一个业务灵巧的组件&#xff0c;它集成了全局搜索和展示搜…

ic基础|功耗篇04:门级低功耗技术

大家好&#xff0c;我是数字小熊饼干&#xff0c;一个练习时长两年半的IC打工人。我在两年前通过自学跨行社招加入了IC行业。现在我打算将这两年的工作经验和当初面试时最常问的一些问题进行总结&#xff0c;并通过汇总成文章的形式进行输出&#xff0c;相信无论你是在职的还是…

《Windows API每日一练》6.2 客户区鼠标消息

第五章已经讲到&#xff0c;Windows只会把键盘消息发送到当前具有输入焦点的窗口。鼠标消息则不同&#xff1a;当鼠标经过窗口或在窗口内被单击&#xff0c;则即使该窗口是非活动窗口或不带输入焦点&#xff0c; 窗口过程还是会收到鼠标消息。Windows定义了 21种鼠标消息。不过…

UE5蓝图快速实现打开网页与加群

蓝图节点&#xff1a;启动URL 直接将对应的网址输入&#xff0c;并使用即可快速打开对应的网页&#xff0c;qq、discord等群聊的加入也可以直接通过该节点来完成。 使用后会直接打开浏览器。

第11章 规划过程组(收集需求)

第11章 规划过程组&#xff08;一&#xff09;11.3收集需求&#xff0c;在第三版教材第377~378页&#xff1b; 文字图片音频方式 第一个知识点&#xff1a;主要输出 1、需求跟踪矩阵 内容 业务需要、机会、目的和目标 项目目标 项目范围和 WBS 可…

【强化学习】第01期:绪论

笔者近期上了国科大周晓飞老师《强化学习及其应用》课程&#xff0c;计划整理一个强化学习系列笔记。笔记中所引用的内容部分出自周老师的课程PPT。笔记中如有不到之处&#xff0c;敬请批评指正。 文章目录 1.1 概述1.2 Markov决策过程1.2.1 Markov Process (MP) 马尔科夫过程1…