P02项目(学习)
★ P02项目
项目描述:安全操作项目旨在提高医疗设备的安全性,特别是在医生离开操作屏幕时,以减少非授权人员的误操作风险。为实现这一目标,我们采用多层次的保护措施,包括人脸识别、姿势检测以及二维码识别等技术。这些技术用于监测医生是否在工作区域内,并根据检测结果触发相应的安全响应机制。如果医生被检测到离开工作区域或操作屏幕,系统将立即采取措施,例如触发警报、锁定医疗设备,以确保患者数据和医疗设备的安全。
职责描述:
1、学习项目。
2、单元测试
学习别人的如何操作日志记录注解
package com.wg.common.annotation;import java.lang.annotation.*;/*** 自定义操作日志记录注解*/
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {/*** 模块*/String title() default "";/*** 功能*/String business() default "";
}
package com.wg.common.aspectj;import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.wg.common.annotation.Log;
import com.wg.common.constant.Constants;
import com.wg.common.entity.OperationLog;
import com.wg.common.entity.User;
import com.wg.common.service.IOperationLogService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.util.Date;/*** 日志aop信息
**/
@Slf4j
@Aspect
@Component
public class LogAspect {@Autowiredprivate IOperationLogService operationLogService;@AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")public void doAfterReturning(Log controllerLog, Object jsonResult) {handleLog(controllerLog, null, jsonResult);}@AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")public void doAfterThrowing(Log controllerLog, Exception e){handleLog(controllerLog, e, null);}protected void handleLog(Log controllerLog, final Exception e, Object jsonResult){try{User user = (User) StpUtil.getSession().get("user");OperationLog operationLog = new OperationLog();operationLog.setStatus(Constants.SUCCESS);if (ObjectUtil.isNotNull(user)){operationLog.setUserName(user.getUserName());operationLog.setNickName(user.getNickName());}if (e != null){operationLog.setStatus(Constants.FAIL);operationLog.setErrorMsg(StrUtil.sub(e.getMessage(), 0, 2000));}operationLog.setTitle(controllerLog.title());operationLog.setOperationTime(new Date());operationLogService.save(operationLog);}catch (Exception exp){log.error("==前置通知异常==");log.error("异常信息:{}", exp.getMessage());exp.printStackTrace();}}
}

学习单元测试
首先实际完成的时候偷懒的方式就是用SquareTest生成。
Controller 测试
Spring 提供了 MockMVC 用于支持 RESTful 风格的 Spring MVC 测试,使用 MockMvcBuilder 来构造MockMvc 实例。MockMvc 有两个实现:
StandaloneMockMvcBuilder:指定 WebApplicationContext,它将会从该上下文获取相应的控制器并得到相应的 MockMvc
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserControllerTest {@Autowiredprivate WebApplicationContext webApplicationContext;private MockMvc mockMvc;@Beforepublic void setUp() throws Exception {mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
DefaultMockMvcBuilder:通过参数指定一组控制器,这样就不需要从上下文获取了
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserControllerTest {private MockMvc mockMvc;@Beforepublic void setUp() throws Exception {mockMvc = MockMvcBuilders.standaloneSetup(new UserController()).build();}
}
下面是一个简单的用例,对 UserController 的 /user/{id} 接口进行测试。
@RestController
@RequestMapping("user")
public class UserController {@GetMapping("/{id}")public User get(@PathVariable("id") String id) {return new User(1, "lst");}@Data@AllArgsConstructorpublic class User {private Integer id;private String name;}}
import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;@RunWith(SpringRunner.class)
@SpringBootTest
public class UserControllerTest {@Autowiredprivate WebApplicationContext webApplicationContext;private MockMvc mockMvc;@Beforepublic void setUp() {mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();}@Testpublic void getUser() {mockMvc.perform(get("/user/1").accept(MediaType.APPLICATION_JSON_UTF8)).andExpect(status().isOk()).andExpect(content().string(containsString("\"name\":\"lst\"")));}}
方法描述
perform:执行一个 RequestBuilder 请求,返回一个 ResultActions 实例对象,可对请求结果进行期望与其它操作
get:声明发送一个 get 请求的方法,更多的请求类型可查阅→MockMvcRequestBuilders 文档
andExpect:添加 ResultMatcher 验证规则,验证请求结果是否正确,验证规则可查阅→MockMvcResultMatchers 文档
andDo:添加 ResultHandler 结果处理器,比如调试时打印结果到控制台,更多处理器可查阅→MockMvcResultHandlers 文档
andReturn:返回执行请求的结果,该结果是一个恩 MvcResult 实例对象→MvcResult 文档
Mock 数据
在单元测试中,Service 层的调用往往涉及到对数据库、中间件等外部依赖。
如果不需要对静态方法,私有方法等特殊进行验证测试,则仅仅使用 Spring boot 自带的 Mockito 即可完成相关的测试数据 Mock。若需要则可以使用 PowerMock,简单实用,结合 Spring 可以使用注解注入。
@MockBean
SpringBoot 在执行单元测试时,会将该注解的 Bean 替换掉 IOC 容器中原生 Bean。
例如下面代码中, ProjectService 中通过 ProjectMapper 的 selectById 方法进行数据库查询操作:
@Service
public class ProjectService {@Autowiredprivate ProjectMapper mapper;public ProjectDO detail(String id) {return mapper.selectById(id);}}
此时我们可以对 Mock 一个 ProjectMapper 对象替换掉 IOC 容器中原生的 Bean,来模拟数据库查询操作,如:
复制代码
@RunWith(SpringRunner.class)
@SpringBootTest
public class ProjectServiceTest {@MockBeanprivate ProjectMapper mapper;@Autowiredprivate ProjectService service;@Testpublic void detail() {ProjectDemoDO model = new ProjectDemoDO();model.setId("1");model.setName("dubbo-demo");Mockito.when(mapper.selectById("1")).thenReturn(model);ProjectDemoDO entity = service.detail("1");assertThat(entity.getName(), containsString("dubbo-demo"));}}
Mockito 常用方法
mock() 对象
List list = mock(List.class);
verify() 验证互动行为
@Test
public void mockTest() {List list = mock(List.class);list.add(1);// 验证 add(1) 互动行为是否发生Mockito.verify(list).add(1);
}
when() 模拟期望结果
@Test
public void mockTest() {List list = mock(List.class);when(mock.get(0)).thenReturn("hello");assertThat(mock.get(0),is("hello"));
}
doThrow() 模拟抛出异常
@Test(expected = RuntimeException.class)
public void mockTest(){List list = mock(List.class);doThrow(new RuntimeException()).when(list).add(1);list.add(1);
}
@Mock 注解
在上面的测试中我们在每个测试方法里都 mock 了一个 List 对象,为了避免重复的 mock,使测试类更具有可读性,我们可以使用下面的注解方式来快速模拟对象:
@RunWith(MockitoJUnitRunner.class)
public class MockitoTest {@Mockprivate List list;public MockitoTest(){// 初始化 @Mock 注解MockitoAnnotations.initMocks(this);}@Testpublic void shorthand(){list.add(1);verify(list).add(1);}
}
when() 参数匹配
@Test
public void mockTest(){Comparable comparable = mock(Comparable.class);//预设根据不同的参数返回不同的结果when(comparable.compareTo("Test")).thenReturn(1);when(comparable.compareTo("Omg")).thenReturn(2);assertThat(comparable.compareTo("Test"),is(1));assertThat(comparable.compareTo("Omg"),is(2));//对于没有预设的情况会返回默认值assertThat(list.get(1),is(999));assertThat(comparable.compareTo("Not stub"),is(0));
}
spy() 监控真实对象
Mock 不是真实的对象,它只是创建了一个虚拟对象,并可以设置对象行为。而 Spy是一个真实的对象,但它可以设置对象行为。
@Test(expected = IndexOutOfBoundsException.class)
public void mockTest(){List list = new LinkedList();List spy = spy(list);//下面预设的spy.get(0)会报错,因为会调用真实对象的get(0),所以会抛出越界异常when(spy.get(0)).thenReturn(3);//使用doReturn-when可以避免when-thenReturn调用真实对象apidoReturn(999).when(spy).get(999);//预设size()期望值when(spy.size()).thenReturn(100);//调用真实对象的apispy.add(1);spy.add(2);assertThat(spy.size(),is(100));assertThat(spy.size(),is(1));assertThat(spy.size(),is(2));verify(spy).add(1);verify(spy).add(2);assertThat(spy.get(999),is(999));
}
reset() 重置 mock
@Test
public void reset_mock(){List list = mock(List.class);when(list.size()).thenReturn(10);list.add(1);assertThat(list.size(),is(10));//重置mock,清除所有的互动和预设reset(list);assertThat(list.size(),is(0));
}
times() 验证调用次数
@Test
public void verifying_number_of_invocations(){List list = mock(List.class);list.add(1);list.add(2);list.add(2);list.add(3);list.add(3);list.add(3);//验证是否被调用一次,等效于下面的times(1)verify(list).add(1);verify(list,times(1)).add(1);//验证是否被调用2次verify(list,times(2)).add(2);//验证是否被调用3次verify(list,times(3)).add(3);//验证是否从未被调用过verify(list,never()).add(4);//验证至少调用一次verify(list,atLeastOnce()).add(1);//验证至少调用2次verify(list,atLeast(2)).add(2);//验证至多调用3次verify(list,atMost(3)).add(3);
}
inOrder() 验证执行顺序
@Test
public void verification_in_order(){List list = mock(List.class);List list2 = mock(List.class);list.add(1);list2.add("hello");list.add(2);list2.add("world");//将需要排序的mock对象放入InOrderInOrder inOrder = inOrder(list,list2);//下面的代码不能颠倒顺序,验证执行顺序inOrder.verify(list).add(1);inOrder.verify(list2).add("hello");inOrder.verify(list).add(2);inOrder.verify(list2).add("world");
}
相关文章:
P02项目(学习)
★ P02项目 项目描述:安全操作项目旨在提高医疗设备的安全性,特别是在医生离开操作屏幕时,以减少非授权人员的误操作风险。为实现这一目标,我们采用多层次的保护措施,包括人脸识别、姿势检测以及二维码识别等技术。这些…...
pandas 笔记:get_dummies分类变量one-hot化
1 函数介绍 pandas.get_dummies 是 pandas 库中的一个函数,它用于将分类变量转换为哑变量/指示变量。所谓的哑变量,就是将分类变量的每一个不同的值转换为一个新的0/1变量。在输出的DataFrame中,每一列都以该值的名称命名 pandas.get_dummi…...
PTE作文练习(一)
目录 65分备考建议 WE模版 范文 Supporting ideas: SWT 65分备考建议 RA重在多听标准的正确的示范,RS重在抓大放小,WFD重在整理错题,以及反反复复的车轮战,FIBRW重在“以对代记” 就是直接看答案,节约时间&#…...
如何做到一套FPGA工程无缝兼容两款不同的板卡?
试想这样一种场景,有两款不同的FPGA板卡,它们的功能代码90%都是一样的,但是两个板卡的管脚分配完全不同,一般情况下,我们需要设计两个工程,两套代码,之后还需要一直维护两个版本。 那么有没有一种自动化的方式,实现一个工程,编译出一个程序文件,下载到这两个不同的板…...
VSCode修改主题为Eclipse 绿色护眼模式
前言 从参加开发以来,一直使用eclipse进行开发,基本官方出新版本,我都会更新。后来出来很多其他的IDE工具,我也尝试了,但他们的主题都把我劝退了,黑色主题是谁想出来?😂 字体小的时…...
conan和cmake编译器版本不匹配问题解决
conan和cmake编译器版本不匹配问题解决 1 问题现象2 解决方法2.1 在CMakeLists.txt禁止编译器检查2.1.1 修改方式 2.2 探查问题出现的根本原因2.2.1 安装升级gcc2.2.2 安装升级g 注 执行环境:ubuntu 1 问题现象 conan要求的编译器版本和cmake检测到的当前的编译器…...
float单精度浮点数如何在计算机中存储
文章目录 1 float型数据组成2 实际举例3 代码测试4 写在最后 1 float型数据组成 按照IEEE浮点标准存储浮点数时,一个float型的值由1个符号位(最左边的位或最高有效位)、8个指数位以及23个小数位依次组成: 符号位为0时表示正数,为1…...
机器视觉在虚拟现实与增强现实中的作用
机器视觉在虚拟现实(VR)和增强现实(AR)中发挥着至关重要的作用。这些技术的核心是计算机视觉领域,重点是让计算机具有“看到”和理解周围世界的能力。 在虚拟现实中,计算机视觉用于创建和处理用户所见的虚…...
红黑数原理及存在原因
我红黑树那么牛,你们为什么不用?_哔哩哔哩_bilibili 面试时经常会被问到红黑树,它到底有什么优点呢? 对于查找数据,数组二分查询速度最快,时间复杂度为O(logN)。但是如果增加和删除数据,数组就…...
Ansible入门—安装部署及各个模块应用案例(超详细)
目录 前言 一、环境概况 修改主机名(可选项) 二、安装部署 1.安装epel扩展源 2.安装Ansible 3.修改Ansible的hosts文件 4.生成密钥 三、Ansible模块使用介绍 Command模块 Shell模块 User模块 Copy模块 File模块 Hostname模块 Yum模块 Se…...
Spring Boot 3系列之-启动类详解
Spring Boot是一个功能强大、灵活且易于使用的框架,它极大地简化了Spring应用程序的开发和部署流程,使得开发人员能够更专注于业务逻辑的实现。在我们的Spring Boot 3系列之一(初始化项目)文章中,我们使用了Spring官方…...
muduo源码剖析之Timer定时器
简介 Timer 类是 muduo 网络库中的一个定时器类,用于在指定的时间间隔后执行某个任务。 Timer 类提供了一系列的方法来创建、启动、停止和删除定时器,以及设置定时器的时间间隔和回调函数等。 在 muduo 网络库中,Timer 类被广泛应用于各种…...
CocosCreator:背景滚动 、背景循环滚动
.CocosCretor版本3.2.1 编辑器VScode 制作游戏背景的循环滚动 import { _decorator, Component, Node } from cc; const { ccclass, property } _decorator;ccclass(MoveingSceneBg) export class MoveingSceneBg extends Component {property(Node)bg01: Node null!;proper…...
中远麒麟堡垒机SQL注入漏洞复现
简介 中远麒麟堡垒机用于运维管理的认证、授权、审计等监控管理,在该产品admin.php处存在SQL 注入漏洞。 漏洞复现 FOFA语法: body"url\"admin.php?controlleradmin_index&actionget_user_login_fristauth&username" 或者 c…...
ActiveMq学习⑨__基于zookeeper和LevelDB搭建ActiveMQ集群
引入消息中间件后如何保证其高可用? 基于zookeeper和LevelDB搭建ActiveMQ集群。集群仅提供主备方式的高可用集群功能,避免单点故障。 http://activemq.apache.org/masterslave LevelDB,5.6版本之后推出了LecelDB的持久化引擎,它使…...
Ansible概述以及模块
目录 一、Ansible概述: 1. Ansible是什么: 2. Ansible的作用: 3. Ansible的特性: 二、Ansible 环境安装部署: 1. 管理端安装 ansible: 2. ansible 目录结构: 3. 配置主机清单: 4. 配置密钥对验证: 三、an…...
Cannot run program “D:\c\IntelliJ IDEA 2021.1.3\jbr\bin\java.exe“
如果你的idea在打开后出现了这个故障 Cannot run program "D:\c\IntelliJ IDEA 2021.1.3\jbr\bin\java.exe" (in directory "D:\c\IntelliJ IDEA 2021.1.3\bin"): CreateProcess error2, 系统找不到指定的文件。 打开IDEA的设置 file --> settings --&…...
案例-注册页面(css)
html页面用css控制样式,画一个注册页面。 页面最终效果如下: 页面代码: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>注册页面</title> <style>*{…...
Ansible--playbook 剧本
一、playbook: playbook是剧本的意思通过 task 调用 ansible 的模块将多个 play 组织在一 个playbook中运行。 1.1 playbook的组成: Tasks:任务,即通过 task 调用 ansible 的模板将多个操作组织在一个 playbook 中运行Variables…...
Vue3.0路由拦截
全局路由器拦截:官方叫导航守卫 index.js路由器 import { createRouter, createWebHistory } from "vue-router"; //导入vue-router路由模块,createWebHashHistor函数const routes [{path: "/", //路径: redirect: "/Films" //涉…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
