Spring Boot实战(三十六)编写单元测试

目录

    • 一、什么是单元测试?
    • 二、Spring Boot 中的单元测试依赖
    • 三、举例 Spring Boot 中不同层次的单元测试
      • 3.1 Service层
      • 3.2 Controller 层
      • 3.3 Repository层
    • 四、Spring Boot 中 Mock、Spy 对象的使用
      • 4.1 使用Mock对象的背景
      • 4.2 什么是Mock对象,有哪些好处?
      • 4.3 使用 Mock 对象的示例
      • 4.4 什么是Spy对象,有哪些好处?
      • 4.5 使用 Spy 对象的示例

一、什么是单元测试?

单元测试 是指对软件中的最小可测试单元进行检查和验证。在 Java 中,单元测试的最小单元是类。通过编写针对类或方法的小段代码,来检验被测代码是否符合预期结果或行为。

执行单元测试可以帮助开发者验证代码是否正确实现了功能需求,以及是否能够适应应用环境或需求变化。


二、Spring Boot 中的单元测试依赖

在 Spring Boot 项目中,要进行单元测试,首先需要添加相应的依赖。Maven 依赖如下:

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

这个依赖包含了多个库和功能,主要有以下几个:

  • JUnit:JUnit 是 Java 中最流行和最常用的单元测试框架,它提供了一套 注解断言 来编写和运行单元测试。例如 @Test 注解表示一个测试方法,assertEquals 断言表示两个值是否相等。
  • Spring Test:Spring Test 是一个基于 Spring 的测试框架,它提供了一套注解和工具来配置和管理 Spring 上下文和 Bean。例如 @SpringBootTest 注解表示一个集成测试类,@Autowired 注解表示自动注入一个 Bean。
  • Mockito:Mockito 是一个 Java 中最流行和最强大的 Mock 对象库,它可以模仿复杂的真实对象行为,从而简化测试过程。例如 @MockBean 注解表示创建一个 Mock 对象,when 方法表示定义 Mock 对象的行为。
  • Hamcrest:Hamcrest 是一个 Java 中的匹配器库,它提供了一套语义丰富而易读的匹配器来进行结果验证。例如 asserThat 断言表示验证一个值是否满足一个匹配器,is 匹配器表示两个值是否相等。
  • AssertJ:AssertJ 是一个 Java 中的断言库,它提供了一套流畅而直观的断言语法来进行结果验证。例如 assertThat 断言表示验证一个值是否满足一个条件,isEqualTo 断言表示两个值是否相等。

除了以上这些库外,spring-boot-starter-test 还包含了其他一些库和功能,如 JsonPath、JsonAssert、XmlUnit 等。这些库和功能可以根据不同的测试场景进行选择和使用。


三、举例 Spring Boot 中不同层次的单元测试

如果是通过spring initialize创建的springboot项目(本系列第一篇文章有讲解),其实会自动创建一个单元测试类:

在这里插入图片描述

我们在写单元测试的时候,直接继承这个类即可。

3.1 Service层

在 Spring Boot 中,对 Service 层进行单元测试,可以使用 @SpringBootTest 注解来加载完整的 Spring 上下文,从而可以自动注入 Service 层的 Bean。同时,可以使用 @MockBean 注解来创建和注入其他层次的 Mock 对象,从而避免真实地调用其他层次的方法,而是模拟其行为。

例如,假设有一个 UserService 类,它提供了一个根据用户 ID 查询用户信息的方法:

@Service
public class UserService {@Autowiredprivate UserRepository userRepository;public User getUserById(Long id) {return userRepository.findById(id).orElse(null);}
}

要对这个类进行单元测试,可以编写以下测试类:

@SpringBootTest
public class UserServiceTest {@Autowiredprivate UserService userService;@MockBeanprivate UserRepository userRepository;@Testpublic void testGetUserById() {// 创建一个User对象User user = new User();user.setId(1L);user.setName("ACGkaka");user.setEmail("acgkaka@example.com");// 当调用userRepository.findById(1L)时,返回一个包含user对象的Optional对象when(userRepository.findById(1L)).thenReturn(Optional.of(user));// 调用userService.getUserId()方法,传入1L作为参数,得到一个User对象。User result = userService.getUserById(1L);// 验证结果对象与user对象相等assertThat(result).isEqualTo(user);// 验证userRepository.findById(1L)方法被调用了一次verify(userRepository, times(1)).findById(1L);}
}

在这个测试类中,使用了以下几个关键点和技巧:

  1. 使用 @SpringBootTest 注解表示加载完成的 Spring 上下文,并使用 @Autowired 注解将 UserService 对象注入到测试类中。
  2. 使用 @MockBean 注解表示创建一个 UserRespository 对象,并使用 @Autowired 注解将其注入到测试类中。这样可以避免真实地调用 UserRepository 的方法,而是模拟其行为。
  3. 使用 when 方法来定义 Mock 对象的行为,例如当调用 userRepository.findById(1L) 时,返回一个包含 user 对象的 Optional 对象。
  4. 使用 userService.getUserById() 方法调用被测方法,得到一个 User 对象。
  5. 使用 AssertJ 的断言语法来验证结果对象与 user 对象是否相等。可以使用多种条件和匹配器来验证结果。
  6. 使用 verify 方法来验证 Mock 对象的方法是否被调用了指定次数。

3.2 Controller 层

Controller 层是指处理用户请求和响应的层,它通常使用 @RestController@Controller 注解来标识。在 Spring Boot 中,对 Controller 层进行单元测试,可以使用 @WebMvcTest 注解来启动一个轻量级的 Spring MVC 上下文,只加载 Controller 层的组件。同时,可以使用 @AutoConfigureMockMvc 注解来自动配置一个 MockMvc 对象,用来模拟 Http 请求和验证 Http 响应。

例如,假设有一个 UserController 类,它提供了一个根据用户ID查询用户信息的接口:

@RestController
@RequestMapping("/users")
public class UserController {@Autowiredprivate UserService userService;@GetMapping("/{id}")public ResponseEntity<User> getUserById(@PathVariable Long id) {User user = userService.getUserById(id);if (user == null) {return ResponseEntity.notFound().build();} else {return ResponseEntity.ok(user);}}
}

要对这个类进行单元测试,可以编写以下测试类:

@WebMvcTest(UserController.class)
@AutoConfigureMockMvc
public class UserControllerTest {@Autowiredprivate MockMvc mockMvc;@MockBeanprivate UserService userService;@Testpublic vid testGetUserById() throws Exception {// 创建一个 User 对象User user = new User();user.setId(1L);user.setName("ACGkaka");user.setEmail("acgkaka@example.com");// 当调用userService.getUserById(1L)时,返回user对象when(userService.getUserById(1L)).thenReturn(user);// 模拟发送GET请求到/users/1,并验证响应状态码为200,响应内容为JSON格式的user对mockMvc.perform(get("/users/1"))mockMvc.perform(get("/users/1")).andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON)).andExpect(jsonPath("$.id").value(1L)).andExpect(jsonPath("$.name").value("ACGkaka")).andExpect(jsonPath("$.email").value("alice@example.com"));// 验证userService.getUserById(1L)方法被调用了一次。verify(userSerivce, times(1)).getUserById(1L);}
}

在这个测试类中,使用了以下几个关键点和技巧:

  1. 使用 @WebMvcTest(UserController.class) 注解表示只加载 UserController 类的组件,不加载其他层次的组件。
  2. 使用 @AutoConfigureMockMvc 注解表示自动配置一个 MockMvc 对象,并使用 @Autowired 注解将其注入到测试类中。
  3. 使用 @MockBean 注解表示创建一个 UserService 的 Mock 对象,并使用 @Autowired 注解将其注入到测试类中。这样可以避免真实地调用 UserService 的方法,而是模拟其行为。
  4. 使用 when() 方法来定义 Mock 对象的行为,例如当调用 userService.getUserById(1L) 时,返回 user 对象。
  5. 使用 mockMvc.perform() 方法来模拟发送 Http 请求,并使用 andExpect 方法来验证 Http 响应。可以使用多种匹配器来验证响应状态码、内容类型、内容值等。
  6. 使用 verify() 方法来验证 Mock 对象的方法是否被调用了指定次数。

3.3 Repository层

在 Spring Boot 中,对 Repository 层进行单元测试,可以使用 @DataJpaTest 注解来启动一个嵌入式数据库,并自动配置 JPA 相关的组件。同时,可以使用 @TestEntityManager 注解来获取一个 TestEntityManager 对象,用来操作和验证数据库数据。

例如,假设有一个 UserRepository 接口,它继承了 JpaRepository 接口,并提供了一个根据用户姓名查询用户列表的方法:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {List<User> findByName(String name);
}

要对这个接口进行单元测试,可以编写以下测试类:

@DataJpaTest
public class UserRepositoryTest {@Autowiredprivate UserRepository userRepository;@Autowiredprivate TestEntityManager testEntityManager;@Testpublic void testFindByName() {// 创建两个User对象,并使用testEntityManager.persist方法将其保存到数据库中User user1 = new User();user1.setName("Bob");user1.setEmail("bob@example.com");testEntityManager.persist(user1);User user2 = new User();user2.setName("Bob");user2.setEmail("bob2@example.com");testEntityManager.persist(user2);// 调用userRepository.findByName()方法,传入“Bob”作为参数,得到一个用户列表。List<User> users = userRepository.findByName("Bob");// 验证用户列表的大小为2,且包含了user1和user2assertThat(users).hasSize(2);assertThat(users).contains(user1, user2);}
}

在这个测试类中,使用了以下几个关键点和技巧:

  1. 使用 @DataJpaTest 注解表示启动一个嵌入式数据库,并自动配置 JPA 相关的组件。这样可以避免依赖外部数据库,而是使用内存数据库进行测试。
  2. 使用 @Autowired 注解将 UserRepository 和 TestEntityManager 对象注入到测试类中。
  3. 使用 testEntityManager.persist() 方法将 User 对象保存到数据库中。这样可以准备好测试数据,而不需要手动插入数据。
  4. 使用 userRepository.findByName() 方法调用自定义的查询方法,得到一个用户列表。
  5. 使用 AssertJ 的断言语法来验证用户列表的大小和内容。可以使用多种条件和匹配器来验证结果。

四、Spring Boot 中 Mock、Spy 对象的使用

4.1 使用Mock对象的背景

在 Spring Boot 中,除了使用 @WebMvcTest 和 @DataJpaTest 等注解来加载特定层次的组件外,还可以使用 @SpringBootTest 注解来加载完整的 Spring 上下文,从而进行更加集成的测试。但是,在这种情况下,可能会遇到一些问题,例如:

  • 测试过程中需要依赖外部资源,如:数据库、消息队列、Web服务等。这些资源可能不稳定或不可用,导致测试失败或超时。
  • 测试过程中需要调用其他组件或服务的方法,但是这些方法的实现或行为不确定或不可控,导致测试结果不可预测或不准确。
  • 测试过程中需要验证一些难以观察或测量的结果,如:日志输出、异常抛出、私有变量值等。这些结果可能需要使用复杂或侵入式的方式来获取或验证。

为了解决这些问题,可以使用 Mock 对象来模拟真实对象行为。

4.2 什么是Mock对象,有哪些好处?

Mock 对象是指在测试过程中替代真实对象的虚拟对象,它可以根据预设的规则来返回特定的值或执行特定的操作。使用 Mock 对象有以下好处:

  • 降低测试依赖: 通过使用 Mock 对象来替代外部资源或其他组件,可以减少测试过程中对真实环境的依赖,使得测试更加稳定和可靠。
  • 提高测试控制: 通过使用 Mock 对象来模拟特定的行为或场景,可以提高测试过程中对真实对象行为的控制,使得测试更加灵活和精确。
  • 简化测试验证: 通过使用 Mock 对象来返回特定的结果或触发特定的事件,可以简化测试过程中对真实对象结果或事件的验证,使得测试更加简单和直观。

4.3 使用 Mock 对象的示例

在 Spring Boot 中,要使用 Mock 对象,可以使用 @MockBean 注解来创建和注入一个 Mock 对象。这个注解会自动使用 Mockito 库来创建一个 Mock 对象,并将其添加到 Spring 上下文中。同时,可以使用 when() 方法来定义 Mock 对象的行为,以及 verify() 方法来验证 Mock 对象的方法调用。

例如,假设有一个 EmailService 接口,它提供了一个发送邮件的方法:

public interface EmailService {void sendEmail(String to, String subject, String content);
}

要对这个接口进行单元测试,可以编写以下测试类:

@SpringBootTest
public class EmailServiceTest {@Autowiredprivate UserService userService;@MockBeanprivate EmailService emailService;@Testpublic void testSendEmail() {// 创建一个User对象User user = new User();user.setId(1L);user.setName("ACGkaka");user.setEmail("acgkaka@example.com");// 当调用emailService.sendEmail方法时,什么也不做doNothing().when(emailService).sendEmail(anyString(), anyString(), anyString());// 调用userService.sendWelcomeEmail方法,传入user对象作为参数userService.sendWelcomeEmail(user);// 验证emailService.sendEmail方法被调用了一次,并且参数分别为user.getEmail()、"Welcome"、"Hello, ACGkaka"verify(emailService, times(1)).sendEmail(user.getEmail(), "Welcom", "Hello, ACGkaka");}
}

在这个测试类中,使用了以下几个关键点和技巧:

  1. 使用 @SpringBootTest 注解表示加载完整的 Spring 上下文,并使用 @Autowired 注解将 UserService 对象注入到测试类中。
  2. 使用 @MockBean 注解表示创建一个 EmailService 的 Mock 对象,并使用 @Autowired 注解将其注入到测试类中。这样可以避免真实地调用 EmailService 的方法,而是模拟其行为。
  3. 使用 doNothing() 方法来定义 Mock 对象的行为,例如当调用 emailService.sendEmail() 方法时,什么也不做。也可以使用 doReturn()、doThrow()、doAnswer() 等方法来定义其他类型的行为。
  4. 使用 anyString() 方法来表示任意字符串类型的参数,也可以使用 anyInt、anyLong、anyObject 等方法来表示其他类型的参数。
  5. 使用 userService.sendEmail() 方法调用被测方法,传入user对象作为参数。
  6. 使用 verify() 方法来验证 Mock 对象的方法是否被调用了指定次数,并且参数是否符合预期。也可以使用 never、atLeast、atMost 等方法来表示其他次数的验证。

4.4 什么是Spy对象,有哪些好处?

除了使用 @MockBean 注解来创建和注入 Mock 对象外,还可以使用 @SpyBean 注解来创建和注入 Spy 对象。Spy 对象是指在测试u工程中部分替代真实对象的虚拟对象,它可以根据预设的规则来返回特定的值或执行特定的操作,同时保留真实对象的其他行为。使用 Spy 对象有以下好处:

  • 保留真实行为: 通过使用 Spy 对象来替代真实对象,可以保留真实对象的其他行为,使得测试更加接近真实环境。
  • 修改部分行为: 通过使用 Spy 对象来模拟特定的行为或场景,可以修改真实对象的部分行为,使得测试更加灵活和精确。
  • 观察真实结果: 通过使用 Spy 对象来返回特定的结果或触发特定的事件,可以观察真实对象的结果或事件,使得测试更加直观和可信。

4.5 使用 Spy 对象的示例

在 Spring Boot 中,要使用 Spy 对象,可以使用 @SpyBean 注解来创建和注入一个 Spy 对象。这个注解会自动使用 Mockito 库来创建一个 Spy 对象,并将其添加到 Spring 上下文中。同时,可以使用 when() 方法来定义 Spy 对象的行为,以及 verify() 方法来验证 Spy 对象的方法调用。

例如,假设有一个 LogService 接口,它提供了一个记录日志的方法:

public interface LogService {void log(String message);
}

要对这个接口进行单元测试,可以编写以下测试类:

@SpringBootTest
public class LogServiceTest {@Autowiredprivate UserService userService;@SpyBeanprivate LogService logService;@Testpublic void testLog() {// 创建一个User对象User user = new User();user.setId(1L);user.setName("Alice");user.setEmail("alice@example.com");// 当调用logService.log方法时,调用真实的方法,并打印参数到控制台doAnswer(invocation -> {String message = invocation.getArgument(0);System.out.println(message);invocation.callRealMethod();return null;}).when(logService).log(anyString());// 调用userService.createUser方法,传入user对象作为参数userService.createUser(user);// 验证logService.log方法被调用了两次,并且参数分别为"Creating user: Alice"、"User created: Alice"verify(logService, times(2)).log(anyString());verify(logService, times(1)).log("Creating user: Alice");verify(logService, times(1)).log("User created: Alice");}
}

在这个测试类中,使用了以下几个关键点和技巧:

  1. 使用 @SpringBootTest 注解表示加载完整的Spring上下文,并使用@Autowired注解将UserService对象注入到测试类中。
  2. 使用 @SpyBean 注解表示创建一个LogService的Spy对象,并使用@Autowired注解将其注入到测试类中。这样可以保留LogService的真实行为,同时修改部分行为。
  3. 使用 doAnswer() 方法来定义Spy对象的行为,例如当调用logService.log方法时,调用真实的方法,并打印参数到控制台。也可以使用doReturn、doThrow、doNothing等方法来定义其他类型的行为。
  4. 使用 anyString() 方法来表示任意字符串类型的参数。也可以使用anyInt、anyLong、anyObject等方法来表示其他类型的参数。
  5. 使用 userService.createUser() 方法调用被测方法,传入user对象作为参数。
  6. 使用 verify() 方法来验证Spy对象的方法是否被调用了指定次数,并且参数是否符合预期。也可以使用never()、atLeast()、atMost() 等方法来表示其他次数的验证。

整理完毕,完结撒花~🌻





参考地址:

1.Spring Boot中如何编写优雅的单元测试,https://blog.csdn.net/TaloyerG/article/details/132487310

2.【快学springboot】在springboot中写单元测试,https://cloud.tencent.com/developer/article/2385462

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

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

相关文章

aws服务(四)文件存储服务S3 介绍使用代码集成

一、介绍 1、简介 Amazon S3 是 Amazon Web Services 提供的一种对象存储服务(Object Storage),用于在云中存储和检索任意数量的数据。它以高可用性、高扩展性和高持久性著称,非常适合用来存储网站资源、数据备份、日志文件、大数据、机器学习输入输出等。 2、主要特性 …

应用信息1.13.0发布

增加工具箱 增加启动器功能 增加布局查看器 增加手动安装和卸载应用 增加APK文件解析 增加应用多选功能 增加查看应用预装版本 增加应用信息和ADB命令导出 修复其它问题... 百度下载&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;1234

【Vue3 实战】插槽封装与懒加载

一、为什么需要插槽&#xff1f;从一个面板组件说起 在电商首页开发中&#xff0c;经常遇到这样的场景&#xff1a; 「新鲜好物」「人气推荐」同样类型模块都需要相同的标题栏&#xff0c;但内容区布局不同 这时候&#xff0c;插槽&#xff08;Slot&#xff09;就像一个「内容…

虚无隧穿产生宇宙(true nothing tunneling) 是谁提出的

是 亚历克斯.维连金 英文名&#xff08;alex vilenkin 或者 Alexander Vilenkin)提出来的。 “虚无隧穿产生宇宙”&#xff08;true nothing tunneling&#xff09;这一概念并非一个标准的物理学术语&#xff0c;它更像是对某些现代宇宙学理论的描述&#xff0c;尤其是涉及宇宙…

postgis:添加索引时提示“对访问方法 gist 数据类型 geometry 没有默认的操作符表“

问题 在对gis表的geom字段创建空间索引时&#xff0c;出现“对访问方法 "gist" 数据类型 geometry 没有默认的操作符表”的提示报错。 解决方案 按系列步骤进行排查并解决。 1.先确认已安装postgis -- 查看postgis版本 SELECT postgis_full_version() 若安装了则…

图论---Prim堆优化(稀疏图)

题目通常会提示数据范围&#xff1a; 若 V ≤ 500&#xff0c;两种方法均可&#xff08;朴素Prim更稳&#xff09;。 若 V ≤ 1e5&#xff0c;必须用优先队列Prim vector 存图。 #include <iostream> #include <vector> #include <queue> #include <…

代码随想录算法训练营第一天:数组part1

今日学习的文章链接和视频链接 ● 自己看到题目的第一想法 ● 看完代码随想录之后的想法 ● 自己实现过程中遇到哪些困难 ● 今日收获&#xff0c;记录一下自己的学习时长 状态 思路理解完成 30% 代码debug完成 60% 代码模板总结并抽象出来 100% 题目 704 二分查找 题目链接…

企业为何要求禁用缺省口令?安全风险及应对措施分析

在当今数字化时代&#xff0c;企业网络安全面临着前所未有的挑战。缺省口令的使用是网络安全中的一个重要隐患&#xff0c;许多企业在制定网络安全红线时&#xff0c;明确要求禁用缺省口令。本文将探讨这一要求的原因及其对企业安全的重要性。 引言&#xff1a;一个真实的入侵场…

PostgreSQL 中的权限视图

PostgreSQL 中的权限视图 PostgreSQL 提供了多个系统视图来查询权限信息&#xff0c;虽然不像 Oracle 的 DBA_SYS_PRIVS 那样集中在一个视图中&#xff0c;但可以通过组合以下视图获取完整的系统权限信息。 一 主要权限相关视图 Oracle 视图PostgreSQL 对应视图描述DBA_SYS_…

【防火墙 pfsense】1简介

&#xff08;1&#xff09; pfSense 有以下可能的用途&#xff1a; 边界防火墙 路由器 交换机 无线路由器 / 无线接入点 &#xff08;2&#xff09;边界防火墙 ->要充当边界防火墙&#xff0c;pfSense 系统至少需要两个接口&#xff1a;一个广域网&#xff08;WAN&#xff0…

数据库+Docker+SSH三合一!深度评测HexHub的全栈开发体验

作为一名技术博主&#xff0c;我最近一直被各种开发工具切换搞得焦头烂额。数据库要用Navicat&#xff0c;服务器管理得开Termius&#xff0c;Docker操作还得切到命令行&#xff0c;每天光在不同工具间切换就浪费了大量时间。直到团队里的一位架构师向我推荐了HexHub这个一体化…

第十天 Shader编程:编写简单表面着色器 Addressable资源管理系统 DOTS(面向数据技术栈)入门

前言 作为Unity初学者&#xff0c;在实现复杂场景时经常会遇到性能瓶颈。本文将带你通过四个关键技术的实战学习&#xff0c;掌握现代Unity开发的核心优化方案&#xff1a; Shader编程 - 编写表面着色器控制物体渲染Addressable系统 - 实现高效资源管理DOTS技术栈 - 解锁百万…

项目自动化测试

一.设计测试用例(细致全面) 二.先引入所需要的pom.xml依赖 1.selenium依赖 2.webdrivermanager依赖 3.commons-io依赖 编写测试用例–按照页面对用例进行划分,每个页面是Java文件,页面下的所有用例统一管理 三.common包(放入公用包) 类1utils 可以调用driver对象,访问url …

ap无法上线问题定位(交换机发包没有剥掉pvid tag)

一中学&#xff0c;新开的40台appoe交换机核心交换机旁挂ac出口路由的组网&#xff0c;反馈ap无法上线&#xff0c;让协助解决。 组网如下&#xff1a; 排查过程&#xff1a; 检查ac的配置&#xff0c;没有发现问题 发现配置没有问题&#xff0c;vlan1000配置子接口&#xff…

第十七届山东省职业院校技能大赛 中职组网络建设与运维赛项

第十七届山东省职业院校技能大赛 中职组网络建设与运维赛项 赛题 B 卷 第十七届山东省职业院校技能大赛中职组网络建设与运维赛项 1 赛题说明 一、竞赛项目简介 “网络建设与运维”竞赛共分为以下三个模块&#xff1a;  网络理论测试&#xff1b;  网络建设与调试&#xf…

关于QT信号、槽、槽函数的讲解

也是好久没有发帖子了&#xff0c;最近博主主要还是在边学QT边完成任务&#xff0c;所以进度很慢&#xff0c;但确实在这几天对于QT自身槽和信号这类特殊的机制有了一定简单的理解&#xff0c;所以还是想记录下来&#xff0c;如果有初学者看到帖子对他有一定的帮助&#xff0c;…

YOLOv8 涨点新方案:SlideLoss FocalLoss 优化,小目标检测效果炸裂!

YOLOv8优化秘籍&#xff1a;用SlideLoss和FocalLoss提升小目标检测精度&#xff08;附代码实战&#xff09;​​ ​&#x1f4cc; 核心问题&#xff1a;YOLOv8在检测小物体时效果不够好&#xff1f;​​ YOLOv8虽然是强大的目标检测模型&#xff0c;但在处理小物体或类别不平…

基于cubeMX的hal库STM32实现MQ2烟雾浓度检测

一、任务目标 使用STM32F103C8T6单片机&#xff0c;使用单片机AD模块采集MQ2烟雾传感器的数据&#xff0c;在OLED屏显示检测到的AD值、电压值和浓度值&#xff08;ppm单位&#xff09;。 二、实现过程 1、MQ2烟雾传感器的浓度转化方法 &#xff08;1&#xff09;实验所用的M…

Android之AI自动化测试--Midscene

文章目录 前言一、准备工作1.安装2.准备 API Key3.安装 adb4.连接设备 二、yaml格式自动化脚本1. 脚本案例2.执行结果 三、文件结构变化android 部分 前言 字节 Web Infra团队官宣Midscene 从 v0.15 开始支持 Android 自动化测试&#xff0c;本篇文章介绍yaml方式的Android自动…

类的六个默认成员函数

如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在什么都不写时&#xff0c;编译器会自动生成以下6个默认成员函数。 默认成员函数&#xff1a;用户没有显式实现&#xff0c;编译器会生成的成员函数称为默认…