超详细 springboot 整合 Mock 进行单元测试!本文带你搞清楚!
文章目录
- 一、什么是Mock
- 1、Mock定义
- 2、为什么使用
- 3、常用的Mock技术
- 4、Mokito中文文档
- 5、集成测试和单元测试区别
- 二、API
- 1、Mockito的API
- 2、ArgumentMatchers参数匹配
- 3、OngoingStubbing返回操作
- 三、Mockito的使用
- 1、添加Maven依赖
- 2、@InjectMocks、@Mock使用
- 3、SpringbootTest 注解和 RunWith 注解在测试类的作用
- 四、Mock 测试代码案例
- 1、添加依赖
- 2、编写业务代码
- 3、Mock 测试
- (1)常规测试
- (2)Mock 测试
- (3)Mock 测试常用方法
- thenReturn 系列方法
- thenThrow 系列方法
- verify 系列方法
- 模拟对象有两种方式
- 对 void 的方法设置模拟
- (4)Mock 测试常用注解
- 五、Mock 测试结合 Java 反射综合案例
一、什么是Mock
1、Mock定义
Mockito是Java单元测试开发框架。在写测试单元时它可以Mock(Mock的中文释义是模拟,所以Mockito从名字上可以看出是要模拟一种场景)。
它可以模拟任何 Spring 管理的 Bean、模拟方法的返回值、模拟抛出异常等,避免为了测试一个方法,却要自行构建整个 bean 的依赖链。
Mock 测试主要是用来进行开发中一些 未完成的接口 或者 网络断开、数据库连接错误 等方法调用。
举个例子:
如下代码所示,list 集合需要从数据库查询出来。但是如果暂时数据库不能用,有需要测试,这个时候就可以进行 Mock 模拟出符合条件的 list 集合进行本地测试,无需连接数据库。
2、为什么使用
在对代码进行单元测试过程中,经常会有以下的情况发生:
class A 依赖 class B
class B 依赖 class C和class D
class C 依赖 ...
class D 依赖 ... 1.被测对象依赖的对象构造复杂
我们想对class A进行单元测试,需要构造大量的class B、C、D等依赖造步骤多、耗时较长的对象,
对于他们的构造我们可以利用mock去构造过程复杂的对象用于class A的测试,
因为我们只是想测试class A的行为是否符合预期,我们并不需要测试依赖对象。2.被测单元依赖的模块尚未开发完成,而被测对象需要依赖模块的返回值进行测试:
----- 比如service层的代码中,包含对dao层的调用,但dao层代码尚未实现
----- 比如web的前端依赖后端接口获取数据进行联调测试,但后端接口并未开发完成
----- 比如数据库还不能正常使用但是需要测试功能逻辑是否可行。
3、常用的Mock技术
- PowerMock
- EasyMock
- Mockito
- JMock
目前在 Java 中主流的 Mock 测试工具有 Mockito、JMock、EasyMock 等等,而 SpringBoot 目前内建的是 Mockito 框架。
4、Mokito中文文档
Mokito中文官网
5、集成测试和单元测试区别
(1)集成测试
测试过程中,会启动整个Spring容器,调用DB 或者 依赖的外部接口等。只不过访问的环境是测试环境。这个过程最大程度还原生产环境过程,但是耗时长。
(2)单元测试
不启动整个应用,只对单个接口/类进行测试。不调用DB 、外部接口,依赖的服务都Mock掉,只测试代码逻辑。这个过程,测试用例耗时短。
二、API
1、Mockito的API
- mock:构建一个我们需要的对象;可以mock具体的对象,也可以mock接口
- spy:构建监控对象
- verify:验证某种行为
- when:当执行什么操作的时候,一般配合thenXXX 一起使用。表示执行了一个操作之后产生什么效果
- doReturn:返回什么结果
- doThrow:抛出一个指定异常
- doAnswer:做一个什么相应,需要我们自定义Answer
- times:某个操作执行了多少次
- atLeastOnce:某个操作至少执行一次
- atLeast:某个操作至少执行指定次数
- atMost:某个操作至多执行指定次数
- atMostOnce:某个操作至多执行一次
- doNothing:不做任何处理
- doReturn:返回一个结果
- doThrow:抛出一个指定异常
- doAnswer:指定一个操作,传入Answer
- doCallRealMethod:返回真实业务执行的结果,只能用于监控对象
2、ArgumentMatchers参数匹配
- anyInt:任何int类型的参数,类似的还有anyLong/anyByte等等。
- eq:等于某个值的时候,如果是对象类型的,则看toString方法
- isA:匹配某种类型
- matches:使用正则表达式进行匹配
3、OngoingStubbing返回操作
- thenReturn:指定一个返回的值
- thenThrow:抛出一个指定异常
- then:指定一个操作,需要传入自定义Answer
- thenCallRealMethod:返回真实业务执行的结果,只能用于监控对象
三、Mockito的使用
1、添加Maven依赖
- Java 环境依赖
<!-- https://mvnrepository.com/search?q=Mockito-->
<dependency><groupId>org.mockito</groupId><artifactId>mockito-core</artifactId><version>4.4.0</version>
</dependency>
- SpringBoot 环境依赖
注意:SpringBoot 默认的 Mock 框架是 Mockito,和 junit 一样,只需要依赖 spring-boot-starter-test 就可以了
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId>
</dependency>
2、@InjectMocks、@Mock使用
- @Mock: 用于代替Mockito.mock创建mock对象,创建一个Mock实例,需要基于JUnit5环境。
- @InjectMocks: 创建一个实例,其余用@Mock(或@Spy)注解创建的mock将被注入到用该实例中。
直白的理解就是:
如图,实体类TUserServiceImpl通过注解 @Autowired
注入了三个实体:TUserMapper、JdbcTemplate 和 NamedParameterJdbcTemplate。
如果想要测试TUserServiceImpl,那么test中,TUserMapper、JdbcTemplate 和 NamedParameterJdbcTemplate就要用@Mock
注解创建Mock实例,而要被测试TUserServiceImpl就要用@InjectMocks
注解创建实例,这个时候被@Mock
注解创建的TUserMapper、JdbcTemplate 和 NamedParameterJdbcTemplate就被注入到通过 @InjectMocks
注解创建的TUserServiceImpl实例中。如下图所示:
最后的大白话解释 !!!
你要测试哪个类(如TUserServiceImpl),那么就用 @InjectMocks
注解;
被测试的类中通过 @Autowired
注解注入了几个,那么测试类里面就用@Mock
注解创建几个实例!
使用Mockito的注解,需要让注解生效,让注解生效的方法有两个:
- 给被测类添加
@RunWith(MockitoJUnitRunner.class)
或者@RunWith(SpringJUnit4ClassRunner.class)
注解
@RunWith(MockitoJUnitRunner.class)
public class MockitoAnnotationTest {...
}
- 在初始化方法中使用
MockitoAnnotations.openMocks(this)
@Before
public void init() {MockitoAnnotations.openMocks(this);
}
注意:新版spring-boot-starter-test不再集成junit,而是junit-jupiter,找不到@RunWith
注解:
- spring-boot-starter-test 2.5.5 版本只需要在类上加上@SpringBootTest即可,不需要再加@RunWith()注解了。
- spring-boot-starter-test 2.4.x 版本的也没有@RunWith()注解,至于从哪个版本开始没有@RunWith()注解的,请自行查阅相关文档。
- 一些较低版本也没有 openMocks 方法,而是 initMocks
3、SpringbootTest 注解和 RunWith 注解在测试类的作用
- @SpringbootTest
这个注解相当于启动类的作用,加了这个注解后,当使用加了@Test注解的方法时,会加载Spring上下文,跟SpringbootApplication这个启动类一样,把bean加载进IOC容器。
其中参数classes 需指明启动类.class,如果不指明,需要保证启动类所在的包和加了SpringbootTest注解的类 在同一个包或者是启动类的子包下,否则注入到( @Autowired / @Resource)会报空指针异常。如下:
@SpringBootTest(classes = MySpringbootApplication.class)
- @RunWith
@RunWith(SpringRunner.class),作用是与Spring环境整合,因为在测试类中我们可以需要用@Autowired自动装配IOC容器中的bean,所以需要与Spring环境进行整合,才能实现自动装配,否则会装配失败,导致bean为null。
有时候会发现,有的测试类不添加@RunWith也能注入成功,这是因为,如果导入@Test注解的包是org.junit.jupiter.api.Test,则不需要添加@RunWith注解,如果导入的是org.junit.Test,则需要添加,这点需要注意。
四、Mock 测试代码案例
1、添加依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency>
注意:本案例用的 springboot 版本是 2.6 版本
2、编写业务代码
@Service
public class PositionService {public String getStr(String str){return str;}public void getVoid(){System.out.println("没有返回值");}}
3、Mock 测试
(1)常规测试
先不使用 Mockito ,而是真的去调用一个正常的 Spring bean ,测试类写法如下。其实就是很普通的注入 PositionService bean,然后去调用他的方法。
测试代码:
注意:
可以看到测试类中引用的包是 org.junit.jupiter.api.Test
和 org.junit.jupiter.api.BeforeEach
,是 jupiter.api
包下面的,此时测试类只用了 @SpringBootTest 这一个注解;
但是,如果用的是 org.junit.Test
和 org.junit.Before
,测试类上面必须同时用 @RunWith(SpringRunner.class)
和 @SpringBootTest(classes = MySpringbootApplication.class)
。必须同时用!!!!!
import com.cyd.applicationstartup.MySpringbootApplication;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeEach;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest(classes = MySpringbootApplication.class)
public class PositionServiceTest {@Autowiredprivate PositionService positionService;@BeforeEachpublic void init() {// 对所有注解了@Mock的对象进行模拟MockitoAnnotations.openMocks(this);System.out.println("初始化方法");}@Testpublic void testGetStr() {String str = positionService.getStr("刘亦菲");System.out.println("测试结果:" + str);}
}
测试结果:
(2)Mock 测试
Mock 测试需要自定返回结果,结果和方法返回结果类型一致。
语法如下:
Mockito.when( 对象.方法名() ).thenReturn( 自定义结果 )
使用 Mockito 模拟 Bean 的单元测试代码示例如下:
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeEach;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest(classes = MySpringbootApplication.class)
public class PositionServiceTest {@Mockprivate PositionService positionService;@BeforeEachpublic void init() {System.out.println("初始化方法");}@Testpublic void testMockGetStr() {// 定义当调用mock positionService 的 getStr() 方法,并且任意字符串参数时,就返回字符串 "刘亦菲"Mockito.when(positionService.getStr(Mockito.anyString())).thenReturn("刘亦菲");// 定义当调用 mock positionService 的 getStr() 方法,并且参数是字符串 "美女" 时,就返回字符串 "刘亦菲"Mockito.when(positionService.getStr("美女")).thenReturn("刘亦菲");System.out.println(positionService.getStr("美女"));// 验证 positionService 的 getStr()这个方法是否被调用过Mockito.verify(positionService).getStr("刘亦菲");}
}
注意:
代码中第一个 Mockito.when 的参数用的是 Mockito.anyString(),表示 任意字符串参数调用 getStr() 方法,就会返回字符串 “刘亦菲”;
第二个 Mockito.when 的参数用的是字符串"美女",表示限制只有当参数是 "美女"时,才会返回 “刘亦菲”。
因此,在日常 Mock 测试中,通常使用 Mockito.any 作为参数。
(3)Mock 测试常用方法
thenReturn 系列方法
① 定义当调用mock positionService 的 getStr() 方法,并且任意字符串参数时,就返回字符串 “哈哈哈哈”:
Mockito.when(positionService.getStr(Mockito.anyString())).thenReturn("哈哈哈哈");
System.out.println(positionService.getStr("任意参数"));
表示任意值的参数如下图:
② 定义当调用 mock positionService 的 getStr() 方法,并且限制参数只有是字符串 “美女” 时,才返回字符串 “刘亦菲”:
Mockito.when(positionService.getStr("美女")).thenReturn("刘亦菲");
System.out.println(positionService.getStr("美女"));
thenThrow 系列方法
① 当调用 mock positionService 的 getStr() 方法,输入的的参数是 字符串 “9” 时,抛出一个 RuntimeException:
Mockito.when(positionService.getStr("9")).thenThrow(new RuntimeException("mock throw exception"));
String str = positionService.getStr("9"); //会抛出一个RuntimeExceptio
测试结果:
② 如果方法没有返回值的话(即是方法定义为 public void myMethod() {…}),要改用 doThrow() 抛出 Exception:
Mockito.doThrow(new RuntimeException("mock throw exception when method is void")).when(positionService).getVoid();
positionService.getVoid(); //会抛出一个RuntimeException
测试结果:
verify 系列方法
① 检查调用 positionService 的 getStr() 方法,、且参数为 “3” 的次数是否为1次:
Mockito.verify(positionService, Mockito.times(1)).getStr(Mockito.eq("3"));
② 验证调用顺序,验证 positionService 是否先调用 getStr() 两次,并且第一次的参数是 “3”、第二次的参数是 “5”,然后才调用 getVoid() 方法:
InOrder inOrder = Mockito.inOrder(positionService);
inOrder.verify(positionService).getStr("3");
inOrder.verify(positionService).getStr("5");
inOrder.verify(positionService).getVoid();
模拟对象有两种方式
- 对注解了 @Mock 的对象进行模拟
MockitoAnnotations.openMocks(this)
; - 对单个对象手动 mock :
xxx= Mockito.mock(xxx.class)
;
对 void 的方法设置模拟
positionService 中有如下方法:
public void getVoidWithParam(String param){System.out.println("没有返回值");}
Mock 测试方法:
/*对void的方法设置模拟*/Mockito.doAnswer(invocationOnMock -> {System.out.println("进入了Mock");return null;}).when(positionService).getVoidWithParam("param");
(4)Mock 测试常用注解
- 全部 Mock
@Mock
private ServiceA serviceA;
这种方式,serviceA中的所有方法都会被mock,并不会真正被调用到
- 依赖注入
ServiceA 依赖了 ServiceC 和 DaoA,使用InjectMocks可以自动注入。
@InjectMocks
private ServiceA serviceA;
- 真实调用
@Spy
private ServiceC serviceC;
这种方式,调用serviceC的方法,会被真实调用。
五、Mock 测试结合 Java 反射综合案例
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;@RunWith(MockitoJUnitRunner.class)
public class MyMockServiceTest {@Mockprivate CustomerDao customerDao;@Mockprivate MockDaoA mockDaoA;@Mockprivate MockDaoC mockDaoC;@Mockprivate MockDaoD mockDaoD;@Mockprivate MockDaoE mockDaoE;@InjectMocksMyMockService myMockService;MockTestDataDto mockTestDataDto;@Beforepublic void init() {// Apollo 配置ReflectionTestUtils.setField(myMockService, "mockValue", "58699DFR-1456984524");MockitoAnnotations.initMocks(this);mockTestDataDto = new MockTestDataDto();mockTestDataDto.setCallback("callback");PolicyRelatedInfo policyRelatedInfo = new PolicyRelatedInfo();policyRelatedInfo.setRelationToAppnt("1");Mockito.when(mockDaoA.selectRelationByParams(Mockito.any())).thenReturn(policyRelatedInfo);Customer customer = new Customer();insu.setPhone("4654");insu.setSex("1");insu.setIdType("1");insu.setIdNo("1");insu.setName("张三");insu.setBirthday(new Date());Mockito.when(customerDao.selectByPrimaryKey(Mockito.anyInt())).thenReturn(customer);}@Testpublic void test() throws NoSuchMethodException, SecurityException, IllegalAccessException,IllegalArgumentException, InvocationTargetException, InstantiationException {ArrayList<PolicyDanger> getPolicyDangerList = new ArrayList<>();PolicyDanger policyDanger1 = new PolicyDanger();policyDanger1.setIsPassFlag("M");policyDanger1.setDanderCode("595648FD");policyDanger1.setTotalAmnt(new BigDecimal(100.1223));PolicyDanger policyDanger2 = new PolicyDanger();policyDanger2.setIsPassFlag("M");policyDanger2.setDanderCode("595648FD");policyDanger2.setTotalAmnt(new BigDecimal(100.1223));getPolicyDangerList.add(policyDanger1);getPolicyDangerList.add(policyDanger2);Mockito.when(mockDaoC.selectPolicyDangerList(Mockito.any())).thenReturn(getPolicyDangerList);ArrayList<Province> provinceList = new ArrayList<>();Province province = new Province();province.setProvinceCode("5894");province.setDutyCode("5928D2");provinceList.add(province);Mockito.when(mockDaoD.selectPolicyByQueryParam(Mockito.any())).thenReturn(provinceList);ArrayList<User> userList = new ArrayList<>();User user = new User();user.setBuyDate(new Date());userList.add(user);Mockito.when(mockDaoE.selectUserByQueryParam(Mockito.any())).thenReturn(userList);// 反射获得类MyMockService hx = new MyMockService();Class<? extends MyMockService> cls1 = hx.getClass();// 通过指定方法名称和参数类型的方法来获取Method对象(注意: 如果方法名称不存在或参数类型不正确的话,会报错,不会返回null)// 注意:这里测试的是 private 修饰的私有方法,需要用 getDeclaredMethod// setUserInfo 是需要测试的方法名,后面为该方法需要的参数类型Method method = cls1.getDeclaredMethod("setUserInfo", MockTestDataDto.class, Integer.class, String.class,SimpleDateFormat.class);method.setAccessible(true);// 执行方法method.invoke(myMockService, mockTestDataDto, 1, "1", new SimpleDateFormat());}
}
注意:
如果测试的类中有如下配置:
@Value("${mock.mapping.name}")private String mockValue;
测试代码中需要如下设置配置值:
ReflectionTestUtils.setField(mockService, "mockValue", "58699DFR-1456984524");
相关文章:

超详细 springboot 整合 Mock 进行单元测试!本文带你搞清楚!
文章目录 一、什么是Mock1、Mock定义2、为什么使用3、常用的Mock技术4、Mokito中文文档5、集成测试和单元测试区别 二、API1、Mockito的API2、ArgumentMatchers参数匹配3、OngoingStubbing返回操作 三、Mockito的使用1、添加Maven依赖2、InjectMocks、Mock使用3、SpringbootTes…...

国产操作系统下Chrome的命令行使用 _ 统信 _ 麒麟
原文链接:国产操作系统下Chrome的命令行使用 | 统信 | 麒麟 Hello,大家好啊!今天我们来聊聊如何在国产操作系统上使用命令行操作Google Chrome。无论是进行自动化测试、网页截图还是网页数据抓取,使用命令行操作Google Chrome都能…...

linux性能监控之slabtop
slabtop命令是以实时的方式显示内核slab缓冲区的细节信息,是linux自带的命令 [rootk8s-master ~]# slabtop --helpUsage:slabtop [options]Options:-d, --delay <secs> delay updates-o, --once only display once, then exit-s, --sort <char&…...

Allure 在 Python 中的安装与使用
Allure 是一个灵活轻量级的测试报告工具,它能够生成详细且富有洞察力的测试报告。在 Python 中,Allure 通常与 Pytest 结合使用,以提供更加丰富的测试结果展示。下面我将介绍关于如何在 Python 中使用 Allure 的详细操作。 一、环境准备 在…...

python实现动态时钟功能
欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 一.前言 时钟,也被称为钟表,是一种用于测量、记录时间的仪器。时钟通常由时针、分针、秒针等计时仪器组成,是现代社会不可或缺的一种计时工具。它的发明和使用极大地改变了人类的生活方式和时间观念。 时钟的类型有很多,…...

QueryPerformanceCounter实现高精度uS(微妙)延时
参考连接 C# 利用Kernel32的QueryPerformanceCounter封装的 高精度定时器Timer_kernel32.dll queryperformancecounter-CSDN博客https://blog.csdn.net/wuyuander/article/details/111831973 特此记录 anlog 2024年5月11日...

Logstash详解
Logstash详解:构建强大日志收集与处理管道的利器 一、引言 在大数据和云计算的时代,日志数据作为企业运营和故障排查的重要依据,其收集、处理和分析能力显得尤为重要。Logstash,作为一款强大的日志收集、处理和转发工具…...

QT设计模式:适配器模式
基本概念 适配器模式(Adapter Pattern)是一种结构型设计模式,允许将一个类的接口转换成客户端所期望的另一个接口,可以让原本由于接口不兼容而不能一起工作的类能够一起工作。 适配器模式需要实现的部分为: Target类…...

开发规范相关
1.对IDEA集成的代码检查 或 AliBaBa的代码检查 定义的规则进行取消或新增 代码自动扫描检查对于代码规范来说至关重要,但有时,我们希望忽略掉某些不必要的检查,比如忽略掉这个检查 可以如下操作 此时即可不再提示告警...

C++ 容器(五)——Set操作
一、Set容器定义 set 是一个有序关联容器,其中的元素按照升序排列,且不允许重复元素。 set 中的元素是唯一的,即任意两个元素不能相等。 1、set 可以用来对元素进行排序,因为它会自动对元素进行有序排列。 2、set 可以用来去重,当我们需要对一个容器中的元素进行去重操…...

【数字IC设计】芯片设计中的RDC
RDC问题定义 在芯片设计中,RDC是reset domain crossing 的缩写,类似于CDC(clock domain crossing),由于现在SOC芯片是有很多ECUs组成,为了使整个系统能够快速从复位中恢复, 用户希望SOC里面每个ECU模块都可以有自己独立的异步复位信号,这样可以在出问题的时候只复位有错…...

spark history server异常
现象:spark 日志文件突然新增了很多.hprof文件, 查找日志spark配置参数spark_log_dir进入日志目录: 查看historyServer日志: Spark Command: /usr/lib/jvm/java-1.8.0/bin/java -cp /opt/apps/JINDOSDK/jindosdk-current/lib/*:/…...

一个优秀 Maven 项目,各 Model 间最佳继承设计方案
1.单一职责原则 (Single Responsibility Principle): 每个模块应该专注于执行一个清晰且明确定义的功能,遵循单一职责原则,以降低模块的复杂性。 2.高内聚性 (High Cohesion): 模块内的组件和类应该紧密相关,共同实现模块的目标。高内聚性…...

MATLAB概述
文章目录 目录结构搜索路径高频命令clearclf/closeclc/homewho/whosformatsave/loadcd/pwdhelp/docsprintf/fprintf/disp tips MATLAB [1] 是美国 MathWorks公司出品的商业 数学软件,用于算法开发、数据可视化、数据分析以及 数值计算的高级技术计算语言和交互式…...

Redis5.0的Stream数据结构
Redis 5.0中引入的Stream数据结构是一种新的、持久化的、可查询的、可扩展的消息队列服务。它可以被视为一个日志或消息队列,由一个有序的、不断增长的日志序列来存储事件流数据。以下是关于Redis 5.0 Stream数据结构的详细解释: 一、Stream数据结构概述…...

避坑指南!RK3588香橙派yolov5生成RKNN模型!
地址1,转换模型 地址2,转换模型 地址3,解决ppa 下载k2 本文目录 一、将.pt模型转为onnx模型文件。(Windows)二、将.onnx模型转为.rknn模型文件。(Linux)三、将.rknn模型部署到开发板RK3588中…...

算法学习笔记(Nim游戏)
N i m Nim Nim游戏 n n n堆物品,每堆有 a i a_i ai个,每个玩家轮流取走任意一堆的任意个物品,但不能不取,取走最后一个物品的人获胜。 N i m Nim Nim游戏是一种经典的公平组合游戏。现在对它进行分析。 首先定义两个博弈中的状…...

第13节 第二种shellcode编写实战(2)
在第二种shellcode编写实战(1)的基础上,新增加一个CAPI类,将所有用到的函数都在这个类中做动态调用的处理,这样使得整个shellcode功能结构更加清晰。 1. 新建类CAPI(即api.h和api.cpp两个文件): api.h&…...

【QuikGraph】C#调用第三方库实现迪杰斯特拉(Dijkstra)算法功能
QuikGraph库介绍 项目地址:https://github.com/KeRNeLith/QuikGraph QuikGraph为.NET提供了通用的有向/无向图数据结构和算法。 QuikGraph提供了深度优先搜索、广度优先搜索、A*搜索、最短路径、k最短路径,最大流量、最小生成树等算法。 QuikGraph最初…...

查看ubuntu当前路径的剩余存储空间
要查看Ubuntu当前路径所在磁盘分区的剩余存储空间,应该使用df命令,而不是du命令,因为df命令能显示磁盘分区的使用情况,包括总容量、已用空间和可用空间。为了使输出更易于阅读,可以加上-h选项。如果你还想知道特定挂载…...

利用预训练模型和迁移学习打造智能狗门
引言 在深度学习的世界里,预训练模型和迁移学习是两个强大的概念,它们允许我们利用已有的模型和知识来解决新的问题。在本博客中,我们将探索如何使用预训练的模型来创建一个智能狗门,这个系统将能够识别狗并允许它们进入…...

常用Linux命令详细总结
一、文档编辑、过滤、查看命令 1、cp 复制文件和目录 -a 复制文件并保持文件属性 -d 若源文件为链接文件,则复制链接文件属性而非文件本身 -i 覆盖文件前提示,如果不要提示,在命令前加上\ -r 递归复制,通常用于目录的复制 …...

基于SpringBoot的竹宣非遗宣传网站
摘要 随着互联网的普及和数字化时代的到来,竹编等非物质文化遗产的保护与传承面临新的机遇和挑战。该研究旨在使用SpringBoot后端框架与Vue前端框架,构建一个竹编非遗宣传网站,通过丰富的展示形式和交互体验,提升公众对竹编这一非…...

怎么清理服务器的C盘?
有时候我们经常会遇到C盘被占满的情况,C盘被占满的原因有很多,下面我们就来分析下有可能导致C盘占满的原因: 第一种情况:中毒 打开服务器任务管理器选择进程,并且勾选显示所有用户的进程,我们可以点击映像…...

动态规划----股票买卖问题(详解)
目录 一.买卖股票的最佳时机: 二.买卖股票的最佳时机含冷冻期: 三.买卖股票的最佳时期含⼿续费: 四.买卖股票的最佳时机III: 五.买卖股票的最佳时机IV: 买卖股票的最佳时机问题介绍:动态规划买卖股票的最佳时机是一个经典的…...

Unity射线检测不到MeshCollider的原因
当我们构建的模型是单面模型时,就会出现射线检测不到MeshCollider的问题,对于渲染,我们可以Cull Off来实现双面渲染,而在射线检测时,Unity提供了一个API来控制是否检测背面:Physics.queriesHitBackfaces 案…...

ssrf初步
一,简介 全称:Server-Side Request Forgery(中文:服务器端请求伪造) 攻击者从服务端发起请求,让服务器连接任意外部系统,从而泄露敏感数据。主要利用各种协议的请求伪造,例如php协…...

linux 安装 mangodb 并设置服务开机自启
1、下载 wget http://mosquitto.org/files/source/mosquitto-1.6.8.tar.gz 2、解压 tar -zxvf mosquitto-1.6.8.tar.gz 3、编译安装cd mosquitto-1.6.8 make sudo make install4、在当前目录。进入mosquitto服务文件存放的文件夹 cd service/systemd可以看到3个文件 点击read…...

Virtualbox7.0.10+Ubuntu20.04网络配置
虚拟机部署在服务器上时,需要进行网络配置,使虚拟机和服务器在同网段下,以保证内网的终端可以访问到虚拟机 1. 设置虚拟机 打开虚拟机设置,选择“网络”,将网卡设为桥接网卡 注:设置前,需要先…...

设计模式之服务定位器模式
想象一下,你的Java应用是一座庞大的迷宫,里面藏着无数宝贵的服务宝藏,而你正需要一张精确的藏宝图来指引方向,迅速找到并利用这些宝藏。服务定位器模式,正是这样一张神奇的地图,它帮你动态定位并获取应用中…...