首页 文章 精选 留言 我的

精选列表

搜索[c 17],共10000篇文章
优秀的个人博客,低调大师

C# GetFiles

var path = AppDomain.CurrentDomain.BaseDirectory + "Images\\Rooms\\"; // string[] patterns = new[] { "*.jpg", "*.jpeg", "*.jpe", "*.jif", "*.jfif", "*.jfi", "*.webp", "*.gif", "*.png", "*.apng", "*.bmp", "*.dib", "*.tiff", "*.tif", "*.svg", "*.svgz", "*.ico", "*.xbm" }; string[] patterns = new[] { "*.jpg", "*.png" }; string[] files = patterns.SelectMany(pattern => Directory.GetFiles(path, pattern, SearchOption.TopDirectoryOnly)).Distinct().ToArray(); // For.NET 4.0 + var files1 = Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories).Where(s => s.EndsWith(".png") || s.EndsWith(".jpg")); // For 2.0, var files2 = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories).Where(s => s.EndsWith(".png") || s.EndsWith(".jpg")); //不支持多种类型同时获取 FileInfo[] fileInfos = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory + "Images\\Rooms\\").GetFiles("*.jpg");

优秀的个人博客,低调大师

C#调试

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo { class Program { static void Main(string[] args) { Console.WriteLine(1000); Console.WriteLine(2000); Console.WriteLine(3000); Console.WriteLine(4000); Console.WriteLine(5000); Console.WriteLine(6000); Console.ReadKey(); } } } 本文转自TBHacker博客园博客,原文链接:http://www.cnblogs.com/jiqing9006/p/6753377.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

C#常量

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Demo { class Program { static void Main(string[] args) { const string myName = "jiqing"; // 定义了一个字符串常量 string name; Console.WriteLine("请输入您的名字:"); name = Console.ReadLine(); if (name.ToLower() == myName) { Console.WriteLine("好巧,我们名字一样!"); } else { Console.WriteLine("我们名字不一样!"); } Console.ReadKey(); } } } 本文转自TBHacker博客园博客,原文链接:http://www.cnblogs.com/jiqing9006/p/6715114.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

iOS - C 应用

前言 1)操作符两端必须加空格,(每行第一个赋值语句对齐)。 2)变量名必须是英文(不能是拼音):英文、数字、下划线和美元符号。 3)等于号 == 反过来写(0 == i%4)防止少些赋值号的错误。 4)通常不省略分支括号。 1、应用 1)质数(素数):质数(prime number)又称素数,有无限个。一个大于 1 的自然数,除了 1 和它本身外,不能被其他自然数整除,换句话说就是该数除了 1 和它本身以外不再有其他的因数;否则称为合数。 2)瑞年:瑞年的条件能满足以下条件之一即可: 1> 能被 4 整除且不能被 100 整除。 2> 能被 400 整除。平年(普通年)有 365 天,瑞年有 366 天。其中,平年的 2 月份只有 28 天,而瑞年二月份有 29 天。 3)最大公约数:最大公因数,也称最大公约数、最大公因子,指两个或多个整数共有约数中最大的一个。 void reduce(int numerator, int denominator) { int u = numerator; int v = denominator; int temp = 0; while(v != 0){ temp = u % v; u = v; v = temp; } NSLog(@"最大公约数为:u = %d", u); } 4)最小公倍数:两个或多个整数的公倍数里最小的那一个叫做它们的最小公倍数。 5)阶乘:一个正整数的阶乘(英语:factorial)是所有小于及等于该数的正整数的积,并且 0 的阶乘为 1。自然数 n 的阶乘写作 n!。 6)水仙花数:水仙花数是指一个 n 位数 ( n≥3 ),它的每个位上的数字的 n 次幂之和等于它本身。(例如:1^3 + 5^3+ 3^3 = 153)。 7)三角数:三角形的第一行包含一个弹球,第二行包含两个弹球,以此类推。一般来说,包含 n 行的三角形可容纳的弹求总数等于 1~n 之间所有整数之和,这个和称为三角数。 8) 冒泡排序 // 冒泡排序 for (int i = 0; i < number - 1; i++) { for (int j = 0; j < number - 1 - i; j++) { if (stu[j] < stu[j + 1]) { temp = stu[j]; stu[j] = stu[j + 1]; stu[j + 1] = temp; } } }

优秀的个人博客,低调大师

《SpringBoot4进阶实战》第17招 测试别全用SpringBootTest

# Petclinic 测试金字塔:从全量 SpringBootTest 到分层切片 ```text 旧方案:所有测试都启动完整 Spring Context → 冲突:测试数量增长后,启动慢、依赖脆弱、故障定位难 → 后果:CI 反馈变慢,开发不敢频繁跑测试,测试系统逐渐失去保护价值 ``` Petclinic 官方项目自带一组测试,但很多团队接手后会把所有测试都写成 `@SpringBootTest`。 我是老李,最近在给一个 Petclinic 改造项目做代码评审,发现测试类里几乎每个用例都加载完整应用上下文。 一开始大家觉得“真实环境最可靠”,可当测试超过 200 个以后,本地跑一遍要十几分钟,CI 经常超时。 为什么“所有测试都是真实 Spring Context”听起来很好,实际却可能得到最慢、最脆弱的测试系统? 应该按什么边界把测试拆成 Pure Unit Test、Web Slice、Data Slice 和完整 @SpringBootTest? 如果选错测试层级,会不会让快速反馈消失,同时让故障定位成本成倍上升? # 01、故事 ```text 周四 23:40 → 公司 CI 服务器 → 修复 Petclinic 账单查询缺陷 → 全量测试跑了 18 分钟还没结束 ``` 晚上十一点多,CI 屏幕上 Petclinic 的测试任务还在转圈。 任务是修复一个账单查询接口的空指针问题,只改了一个 Service 方法。 旁边同事在催发布窗口,运维等着打包,可测试套件像被粘住一样。 我打开日志,发现几百个测试都在重复启动同一个 Spring 上下文,Bean 初始化日志刷了几十屏。 想定位失败用例,却要先从一堆上下文启动耗时里找真正的断言错误。 > 夜深构建仍未归, > 满屏 Bean 载如潮水。 > 只改一行查询错, > 却等全量测试陪。 # 02、问题 ```text 需求变化:测试数量从几十增长到几百 → 冲突:所有用例共享完整 Spring Context 启动成本 → 后果:反馈慢、环境依赖多、失败原因被淹没 ``` 全量 `@SpringBootTest` 会加载所有配置类、数据源、事务管理器、Web 容器和第三方客户端。 测试数量少时,这点开销不明显;数量一多,每个测试类都可能触发新的上下文缓存键。 只要某个 `@MockBean`、`@TestPropertySource` 或 profile 不同,Spring 就会重新创建上下文。 结果 CI 时间线性甚至指数上升,本地开发也不敢频繁跑测试。 可验证的验收标准是:同一组核心用例,分层后总耗时下降 50% 以上,失败日志能直接指向业务断言。 > 真实二字最诱人, > 全量启动却伤身。 > 缓存键变上下文, > 慢与脆从根上生。 # 03、原理 ```text 测试金字塔核心机制:按集成广度分层 → 越底层启动越少 Spring 基础设施 → 越顶层越接近生产,但数量应越少 ``` JUnit Jupiter 负责生命周期与扩展模型,AssertJ 负责可读断言,MockMvc 负责 Web 层切片。 Spring Test 的 `ApplicationContextRunner` 和 `@DataJpaTest` 等切片注解,只加载当前层需要的 Bean。 Pure Unit Test 不启动 Spring,直接 new 对象并注入 Mockito mock,速度最快。 Web Slice 使用 `@WebMvcTest`,只加载 Controller、ControllerAdvice、Filter 等 Web 组件。 Data Slice 使用 `@DataJpaTest`,只加载 JPA 映射、Repository 和嵌入式数据库。 完整 `@SpringBootTest` 加载所有 Bean,适合少量端到端冒烟测试。 反直觉的是:测试越“真实”,并不等于越能快速发现业务错误;真实上下文反而会放大环境噪声。 > 分层不是偷懒计, > 各守边界最清晰。 > 全量只做冒烟用, > 快速反馈靠底层。 # 04、架构 ```text 输入:Petclinic 测试需求 → 本模块:四层测试体系 → 输出:不同启动成本、验证边界与故障定位能力 ``` 第一层 Pure Unit Test 验证 Service、Validator、工具类纯逻辑,不加载 Spring。 第二层 Web Slice 验证 Controller 参数绑定、校验、异常映射和 HTTP 状态码。 第三层 Data Slice 验证 Repository 查询、审计字段和事务回滚行为。 第四层 Full SpringBootTest 验证配置装配、核心链路和外部依赖集成。 收益是启动成本从高到低分布,数量从少到多分布,形成金字塔。 代价是需要团队理解每层边界,避免把同一逻辑重复测试。 适用条件是应用具备清晰分层,Controller、Service、Repository 职责不混乱。 > 四层如塔立工程, > 底层最多顶层精。 > 各测边界不越位, > 快慢分明排障轻。 # 05、第一版实战 ```text 环境:Spring Boot 4 + Java 21 + Maven → 配置:保留官方 Petclinic 依赖 → 代码:先写一个全量 @SpringBootTest 验证账单查询 → 启动:mvn test → 验证:观察 Bean 数量与耗时 → V1:全量测试通过但成本高 ``` 在 `pom.xml` 中确认测试依赖包含 `spring-boot-starter-test`、`spring-boot-testcontainers` 和 `junit-jupiter`。 ```xml org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-testcontainers test ``` 创建全量测试类 `BillingServiceFullContextTest`。 ```java @SpringBootTest class BillingServiceFullContextTest { @Autowired private BillingService billingService; @Test void shouldFindBillByVisitId() { Bill bill = billingService.findByVisitId(100L); assertThat(bill).isNotNull(); assertThat(bill.getAmount()).isPositive(); } } ``` 运行测试并统计上下文启动信息。 ```bash mvn -Dtest=BillingServiceFullContextTest test ``` 示例输出显示加载了大量与账单无关的 Bean。 ```text 示例输出: Started PetclinicApplication in 8.2 seconds Loaded 412 beans ``` V1 测试通过,但一个简单查询也要启动整个应用。 > 全量测试先落地, > 四百 Bean 皆加载。 > 查询一行虽通过, > 八秒启动已嫌多。 # 06、排查 ```text 诊断树:测试慢 → 怀疑全量上下文启动 → 检查 Spring Test 上下文缓存 → 发现不同测试类因注解差异反复重建 → 根因:上下文缓存键不一致 ``` 第一个问题是测试总耗时异常增长。 怀疑是每个测试类都启动新上下文,于是检查测试报告中的上下文缓存命中情况。 ```bash mvn test -Dspring.test.context.cache.max.size=32 -Dspring.test.context.cache.diagnostics=always ``` 日志显示多个上下文键不同,原因是不同测试类使用了不同的 `@MockBean` 或 profile。 ```text 示例输出: Context cache key mismatch due to @MockBean differences ``` 第二个问题是失败日志被启动信息淹没。 检查 CI 日志,发现前 200 行都是 Bean 初始化,真正的断言失败在最后。 根因是全量测试把环境准备和业务验证混在一起。 **错误尝试:** 曾尝试只调大 JVM 堆内存,结果启动时间没明显下降,反而掩盖了上下文重复创建问题。 > 慢病不只在内存, > 缓存键异最伤神。 > 日志翻尽无断言, > 根因藏在上下文。 # 07、优化 ```text V1:全量 @SpringBootTest 验证账单查询 → 证据:412 Bean、8.2 秒启动、失败日志难定位 → V2:拆成 Pure Unit、Web Slice、Data Slice 和少量全量测试 ``` 先为 `BillingService` 写 Pure Unit Test,不启动 Spring。 ```java class BillingServicePureUnitTest { private BillingRepository billingRepository; private BillingService billingService; @BeforeEach void setUp() { billingRepository = mock(BillingRepository.class); billingService = new BillingService(billingRepository); } @Test void shouldReturnBillWhenExists() { Bill bill = new Bill(); bill.setAmount(BigDecimal.TEN); when(billingRepository.findByVisitId(100L)).thenReturn(Optional.of(bill)); Bill result = billingService.findByVisitId(100L); assertThat(result.getAmount()).isEqualByComparingTo("10.00"); } } ``` 再为 Controller 写 Web Slice。 ```java @WebMvcTest(BillingController.class) class BillingControllerWebSliceTest { @Autowired private MockMvc mockMvc; @MockitoBean private BillingService billingService; @Test void shouldReturnBillJson() throws Exception { Bill bill = new Bill(); bill.setAmount(BigDecimal.TEN); when(billingService.findByVisitId(100L)).thenReturn(bill); mockMvc.perform(get("/bills/100")) .andExpect(status().isOk()) .andExpect(jsonPath("$.amount").value(10.0)); } } ``` 为 Repository 写 Data Slice。 ```java @DataJpaTest class BillingRepositoryDataSliceTest { @Autowired private BillingRepository billingRepository; @Test void shouldFindByVisitId() { Bill bill = new Bill(); bill.setVisitId(100L); bill.setAmount(BigDecimal.TEN); billingRepository.save(bill); Optional result = billingRepository.findByVisitId(100L); assertThat(result).isPresent(); assertThat(result.get().getAmount()).isEqualByComparingTo("10.00"); } } ``` 保留一个全量冒烟测试验证核心链路。 ```java @SpringBootTest class PetclinicApplicationSmokeTest { @Test void contextLoads() { } } ``` > 拆开之后天地宽, > 各层只载自家 Bean。 > 单测毫秒即反馈, > 切片秒级可排障。 # 08、演进 ```text V2:四层测试体系 → 能力:按启动成本与验证边界分层 → 遗留:全量测试仍依赖真实数据库或 Testcontainers ``` 用同一组账单查询需求验证前后差异。 Pure Unit Test 不加载 Spring,运行时间通常小于 1 秒。 Web Slice 只加载 Web 相关 Bean,Bean 数量约 30 到 60 个,启动约 2 到 3 秒。 Data Slice 只加载 JPA 相关 Bean,Bean 数量约 40 到 80 个,启动约 2 到 4 秒。 全量测试 Bean 数量超过 400,启动约 8 到 12 秒。 分层后核心测试总耗时从 18 分钟下降到约 6 分钟,失败日志直接显示业务断言。 代价是测试类数量增加,需要维护更多测试文件。 适用场景是持续集成频繁运行、团队需要快速反馈。 遗留问题是全量测试仍依赖数据库状态,下一篇可引入 Testcontainers 固定外部依赖。 > 同组需求前后比, > 耗时减半日志清。 > 分层不是万能药, > 外部依赖待固定。 # 09、洞见 ```text 从现象到判断:测试慢与脆不是硬件问题,而是上下文边界问题 ``` ## 测试速度由上下文启动次数决定,而不是测试数量 ```text 测试数量多 → 上下文缓存命中高 → 速度可接受 上下文键差异多 → 反复启动 → 速度崩塌 ``` 反直觉判断:增加 100 个相同上下文的测试,可能只增加几秒;增加 5 个不同 `@MockBean` 的测试类,可能增加几十秒。 ## 真实上下文会掩盖业务错误 ```text 全量启动 → 环境噪声多 → 失败原因被淹没 切片启动 → 只留当前层 → 断言失败直接可见 ``` 反直觉判断:测试越接近生产,排障体验可能越差,因为失败可能来自任意一个 Bean。 ## 测试金字塔是反馈频率设计 ```text 底层测试多 → 反馈快 → 开发敢频繁跑 顶层测试少 → 反馈慢 → 只做发布前验证 ``` 测试体系的目标不是覆盖所有组合,而是让高频反馈足够快,低频验证足够真实。 > 慢与脆非天命, > 边界不清是根因。 > 分层之后方明白, > 快慢皆在上下文。 # 10、系统落地 ```text 入口:开发者提交代码或本地运行测试 → 服务:Maven Surefire 执行 JUnit Jupiter → 本模块:四层测试体系 → 存储:H2 或 Testcontainers 数据库 → 未实现:外部依赖固定与并行测试 ``` 原来 Petclinic 只有少量官方测试,且多数依赖完整上下文。 本篇增加了 Pure Unit Test、Web Slice、Data Slice 和全量冒烟测试的分层结构。 现在能按启动成本选择测试层级,快速定位 Controller、Service 或 Repository 问题。 下一篇缺少 Testcontainers 固定数据库和消息队列等外部依赖,避免测试受环境漂移影响。 官方文档可参考 Spring Boot 测试主页:https://spring.io/projects/spring-boot > 原是小测不成军, > 今有四层可守城。 > 快速反馈护开发, > 外部依赖待固定。 # 11、小结 ```text 三问三答: 全真实上下文为何慢?→ 上下文缓存键差异导致反复启动 如何分层?→ Pure Unit、Web Slice、Data Slice、Full SpringBootTest 选错后果?→ 反馈慢、排障难、测试系统失去保护价值 ``` 全真实上下文慢,是因为不同测试类注解差异导致 Spring 反复创建上下文。 分层按集成广度划分,底层不启动 Spring,上层只加载当前层 Bean。 选错层级会让快速反馈消失,故障定位成本成倍上升。 当前 Petclinic 测试体系已具备四层结构,核心链路耗时下降,失败日志更清晰。 > 三问皆有解, > 分层是正途。 > 快慢各有位, > 测试护工程。 # 12、作业 ```text 理解→实战→排障→架构判断 ``` ## 理解题:为什么 `@WebMvcTest` 比 `@SpringBootTest` 启动更快? `@WebMvcTest` 只加载 Controller、ControllerAdvice、Filter 等 Web 组件,不加载 Service、Repository、数据源等完整 Bean,因此上 下文更小,启动更快。 ## 实战题:把 Petclinic 的 `OwnerController` 测试从全量改为 Web Slice,并比较 Bean 数量。 使用 `@WebMvcTest(OwnerController.class)`,用 `@MockitoBean` 模拟 `OwnerService`,通过 MockMvc 验证 `/owners` 返 回 200。运行后观察日志中的 Bean 数量,通常从 400 多降到几十个。 ## 排障题:Data Slice 测试通过,但全量测试中 Repository 查询失败,可能是什么原因? 可能是全量测试使用了真实数据库或不同 schema,而 Data Slice 默认使用嵌入式 H2;也可能是全量上下文中有额外配置覆盖了 JPA 属性。检查数据源配置和初始化脚本差异。 ## 架构判断题:是否应该把所有 Service 测试都写成 Pure Unit Test? 不应该。纯逻辑 Service 适合 Pure Unit Test,但涉及事务、审计或复杂 JPA 查询的 Service,需要 Data Slice 或全量测试验证集成行为。 分层依据是验证边界,而不是类名。 > 四题如梯步步高, > 理解实战再排障。 > 架构判断最难得, > 边界清晰方为高。 # 13、升华 ```text 工程结论:测试系统的价值不在于“真实”,而在于反馈速度与故障定位能力的平衡 ``` Petclinic 测试金字塔证明,全量 Spring Context 不是默认选择,而是少量冒烟测试的专用工具。 Pure Unit Test 保护业务逻辑,Web Slice 保护 HTTP 边界,Data Slice 保护持久化边界。 当测试按启动成本分层后,开发才敢频繁运行测试,CI 才能快速反馈。 下一篇将引入 Testcontainers 固定数据库和外部依赖,让全量测试也能稳定可重复。 > 莫把真实当信仰, > 分层方得反馈快。 > 测试如塔守工程, > 快慢相济方不败。 **系列项目:** 基于 Spring 官方 Petclinic 的宠物医院管理系统 **已完成:** 环境搭建、启动机制、依赖与自动配置、配置体系、Web 层、安全层、数据层、事务管理、远程调用、数据库迁移、缓存、并发控制、日志、测试基础、Testcontainers、Docker Compose、Actuator、可观测、自定义自动配置、容器构建、生产上线 **本篇:** 测试金字塔分层体系,Pure Unit、Web Slice、Data Slice 与全量 SpringBootTest 的边界与成本比较 **下一篇:** 用 Testcontainers 固定外部依赖,提升全量测试稳定性与可重复性

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册