win7本机做网站,自己电脑做网站服务器小工具,中国手机网站,大品牌vi设计前言
大家好我是聪。相信有不少的小伙伴喜欢写代码#xff0c;但是对于单元测试这些反而觉得多此一举#xff0c;想着我都在接口文档测过了#xff01;还要写什么单元测试#xff01;写不了一点#xff01;#xff01; 由于本人也是一个小小程序猿#x1f649;#xf…前言
大家好我是聪。相信有不少的小伙伴喜欢写代码但是对于单元测试这些反而觉得多此一举想着我都在接口文档测过了还要写什么单元测试写不了一点 由于本人也是一个小小程序猿我以前也不喜欢写最近给扔到了另一个 leader 的项目组里面刚进去他给我下达的命令就是你写的代码逻辑都要给我写上单元测试而且要生成覆盖率报告给我哇我顿时就难受了我之前都没有这么严格的但是呢最近在我疯狂的写单元测试下我发现我爱上了写单元测试。
单元测试的成长历程
第一次接触单元测试还是在大学的测试课程里面。老师巴拉巴拉的讲我虽然能听懂但是不知道有啥用课程作业反正做起来也没啥难度反正能输出完事。
还有些接触单元测试就是平时学习视频的时候跟着博主教的敲这种简单的比如测试一个Mybatis 查询功能的单元测试在我之前看来soso 我直接用 swagger 文档请求岂不是更方便代码都不用写咯。 直到我接触到了公司项目的单元测试刚来公司看见之前的老项目单元测试都是成堆成堆的写我也不是很理解由于老项目的负责员工不知道换了多少代新负责的都没调试过单元测试直接代码改动导致项目现在的单元测试很多环境配置都没及时更新无法正常启动。当然也没人理会。
最近接触单元测试就是来到了新项目组这边的要求我才重新看清了单元测试的重要性请听我娓娓道来~
单元测试究竟能干嘛
单元测试究竟能干嘛这个问题时常疑惑着我毕竟很多时候都是一个人从零到一进行开发或者接收项目能有好同事手把手教导能大概了解整个项目的运行过程直到我来到了一个用 AI 来生成业务的一个项目组里面一切都发生了改变。
我总结了单元测试的几点好处 能帮助接手项目的人快速了解项目的流程。 这点真的很重要我新接手项目的时候就只有同事简单的说了几句话我甚至只能知道这项目是 AI 提问回答流程然后我直接懵逼不过通过单元测试我一步步看来下倒是能大概了解了项目整体的逻辑。 降低代码出错的概率。 每次在原有接口进行了一系列改动在没有单元测试之前都要自己去接口文档手动尝试甚至引来了测试一大堆指责。在使用单元测试之后新增完的代码逻辑直接新增对应功能的单元测试直接全部执行如果都能通过这代码出问题的概率将会大大减少 不用担心影响数据库的数据。 运行单元测试对于很多环境配置都可以直接使用独立的数据库比如说 MySQL 的数据可以使用 H2 数据库而 Redis 又可以使用 RedisServer 来创建。
单元测试的小技巧
对于单元测试我总结了一些我自己使用中的小技巧这些小技巧的使用往往能有奇效 抽象测试类
SpringBootTest(classes { Application.class, },webEnvironment SpringBootTest.WebEnvironment.MOCK,properties {spring.profiles.activetest}
)
Slf4j
AutoConfigureMockMvc
public abstract class TestBase {
protected static final Long TEST_GROUP_ID 1L;
Autowiredprotected MockMvc mockMvc;
}这个测试类直接打上了需要使用的注解后续使用直接继承即可不用每次写上繁琐的注解示例代码如下
class Test extends TestBase {}在 Spring 项目中使用 H2 代替 MySQL
引入 H2 依赖 dependencygroupIdcom.h2database/groupIdartifactIdh2/artifactIdscoperuntime/scope/dependency通过 application-test.yml 来配置 H2 数据源 spring:datasource:driver-class-name: org.h2.Driverschema: classpath:db/schema.sql #H2 数据库的建表语句data: classpath:db/data.sql #H2 数据库的插入数据语句url: jdbc:h2:mem:test #H2 数据库的默认连接地址username: testpassword: test完成上面的步骤后H2 数据库其实就已经替代掉 MySQL 了但是要注意的是 MySQL 的 sql 语句与 H2 的有一丢丢的差别语法可能并不适用分享一个 IDEA 的插件就可以解决这个问题。 在单元测试中使用 Redis
有不少小伙伴总不喜欢在本地启动一个 Redis 那么单元测试有什么解决办法呢当然有这就用到了 embedded-redis 的一个库使用超级简单。
引入 embedded-redis 依赖 dependencygroupIdit.ozimov/groupIdartifactIdembedded-redis/artifactIdversion0.7.3/versionscopetest/scope!-- 不排除掉slf4j的话 会冲突--exclusionsexclusiongroupIdorg.slf4j/groupIdartifactIdslf4j-simple/artifactId/exclusion/exclusions/dependency直接在单元测试中编写 private static RedisServer redisServer;BeforeAllpublic static void beforeAll() {redisServer RedisServer.builder().setting(maxheap 200m).port(6379).build();redisServer.start();}Spring 单元测试 mock 数据
在我最近接收这个项目中调用 AI 花费是十分昂贵的总不能单元每次都要调用 AI不仅烧钱而且还有不确定性。有些需要 mock 的数据就可以使用 Mockito 这个强大的库来进行操作。
引入依赖虽然说 SpringBoot 中会自带但有时候我嫌弃他的版本不够高但我又不能改 SpringBoot 依赖就使用了覆盖。 dependencygroupIdorg.mockito/groupIdartifactIdmockito-core/artifactIdscopetest/scope/dependencydependencygroupIdorg.mockito/groupIdartifactIdmockito-inline/artifactIdversion3.12.4/versionscopetest/scope/dependencydependencygroupIdorg.mockito/groupIdartifactIdmockito-junit-jupiter/artifactIdversion3.12.4/versionscopetest/scope/dependencymock 要代理的服务。 举个例子我要 mock 一个类的方法首先可以直接使用 MockBean 注解来代理这个注解跟 Autowired 注解类似也是让代理创建。接着就是让单元测试执行前先将这个 Spring 代理对象 mock 创建它给他指定返回的数据内容。示例代码如下 MockBeanprivate TestAgent testAgent;BeforeEachpublic void beforeEach() {Mockito.when(testAgent.answer(any(), any())).thenAnswer(invocation - {return 预期结果});}这里有几个注意的点
1 这里的 any() 就是对应的输入任何数据都要返回这个预期结果其他的还可以自定义。
2 这里的代理只能返回一条数据或者里面自定义规则来返回不同数据如果要每次都按顺序返回可以使用另一种方法 SideEffect 。使用 SideEffect 来进行 mock 返回。
跟上面直接流程一样但是不一样的是 thenAnswer 的后续处理输入是一个 List 里面会按 List 内容的顺序依次返回。示例代码如下 ListString list new ArrayList();list.add(聪1);list.add(聪2);list.add(聪3);Mockito.when(testAgent.answer(Mockito.any(), Mockito.any())).thenAnswer(new SideEffect(list));不想启动 Spring 容器
不想启动 Spring 容器但是代码中用到了 Spring 的代理SpringBoot 容器的启动十分的慢对于我的电脑但是我要进行单元测试的部分其实并不涉及 Spring 我直接进行 AI 请求访问而已接着就可以使用我以下的方法直接启动。 在单元测试中有移除 Spring 相关注解。 移除掉注解后在类上面打上 ExtendWith(MockitoExtension.class) 注解示例代码如下 ExtendWith(MockitoExtension.class)class Test {....}对于交由 Spring 创建的对象进行手动创建。 示例代码如下 // 不用使用注解private TestAgent testAgent;BeforeEachvoid setUp() {testAgent new TestAgent();}后面直接使用对象直接请求即可。
最后 我想我大抵是疯了我喜欢上了写单元测试单元测试写完根本停不下来再未来我会总结更多的单元测试小方法如果你们有自己总结的一些关于单元测试的方法欢迎大家一起分享学习~ 最后最后我是聪希望可以跟大家一起学习我的 Githubgithub.com/lhccong 如果里面有你感兴趣的项目不妨给我点个星星⭐和关注未来我还会持续写新的好玩的小项目。