Boot 测试边界实验(U25)
独立新增工程:Liberica JDK21.0.11+11、Boot4.0.9 / Framework7.0.10、Security7.0.8;本机macOS arm64。依赖由4.0.9 parent/BOM解析,web 模块公开 dependency:tree 核对 spring-test 7.0.10 / spring-boot-test 4.0.9。六个互不混拼的模块分别回答一个测试边界问题:context(TestContext缓存)、tx(事务测试真实回滚/提交)、web(MockMvc与真实端口对照)、slices(Boot4切片范围)、slice-security(切片安全对照)、client(RestClient错误路径)。
从仓库根运行完整公开入口:
JAVA_HOME=$(/usr/libexec/java_home -v21) python3 labs/boot-testing/run.py需要Python3、Maven、本机JDK21,以及本机 127.0.0.1 可达的MySQL(root空密码)与Redis(6379)。MySQL只使用每次运行独有的合成库 u25_<uuid>(结束后DROP);Redis只用database 13与独有key前缀 u25:<uuid>:(只删除自己的key);凭据不同则相应组如实失败。每个命令600秒上限;client 模块的受控HTTP服务绑定loopback随机端口;入口finally之外无常驻进程。原始日志在 ~/.cache/software-engineering-study/java-depth-impl/u25/runtime/,短产物为evidence。
断言表(全部为真实JUnit断言,非日志判读)
| 模块 | 实际断言与观察 |
|---|---|
| context | 同配置两个测试类→1次上下文创建且同一实例;@ActiveProfiles、内联@TestPropertySource 各强制新上下文;@DirtiesContext 类先复用缓存、类后旧上下文关闭、再需同配置时重建新实例(全程 4 refresh / 1 close,事件序列逐行断言) |
| tx | @Transactional 测试内插入可见(1);下一方法回滚后不存在(0);@Commit 后由池外全新MySQL连接看到真实提交(1)并清理;合成库DROP前断言无遗留行 |
| web | standalone MockMvc:匿名访问受保护端点200(无安全链);@SpringBootTest+@AutoConfigureMockMvc:匿名401/错口令401/用户200/越权403/OPS 200,且addFilters=false时匿名200;@MockitoBean UserDetailsService:mock口令200而生产口令401;RANDOM_PORT真实Tomcat:同一矩阵+401带WWW-Authenticate: Basic质询头 |
| slices | @WebMvcTest:切片内唯一OrderService是mock、JdbcTemplate为0、控制器在场;Boot4实测:无spring-boot-security-test时切片0条SecurityFilterChain、匿名200直达控制器;@JdbcTest+replace=NONE连真实MySQL:JdbcTemplate=1、控制器/DispatcherServlet=0,同事务可见1、下一方法回滚0;@DataRedisTest连本机Redis database13:真实PONG、自有key写读删 |
| slice-security | 类路径加spring-boot-security-test后:切片1条SecurityFilterChain、匿名401、mock身份源完成认证200——与slices模块裸切片形成同版本对照 |
| client | JDK内置HttpServer受控服务:200正常路径;500→RestClientResponseException(exchange()可手动处理);读超时→ResourceAccessException(实测cause为java.net.http.HttpTimeoutException);连接被拒→ResourceAccessException(cause为java.net.ConnectException) |
| 负例 | WebMvcSliceMissingServiceProbe(类名不带Test,仅由入口以-Dtest显式执行):不给@MockitoBean补位时@WebMvcTest上下文加载失败,surefire报告记录UnsatisfiedDependencyException: Error creating bean with name 'apiController',Maven退出码1如实登记 |
关键Boot4差异(实测+源码双重核对)
@MockBean 在Boot4.0.9已被移除(旧包路径404),替身注解是Framework spring-test的 @MockitoBean(org.springframework.test.context.bean.override.mockito);@WebMvcTest/@AutoConfigureMockMvc/@JdbcTest/@DataRedisTest 的包名全部从 org.springframework.boot.test.autoconfigure.* 迁移到按技术拆分的新模块(如 org.springframework.boot.webmvc.test.autoconfigure)。Boot4还把切片的安全自动配置拆到独立artifact spring-boot-security-test:只有starter-security时切片没有安全链(匿名直达控制器),加上该模块后恢复401——两组模块即为该结论的对照实验。
只重跑受影响的组
完整入口默认重建并跑全部(六个模块正测试→负例探针→依赖树→evidence)。模块之间没有共享状态:只改某个模块可单独 mvn -q -pl <module> test 后用run.py同参数重跑;evidence只在完整入口下重写,不把分段运行拼成一次调用。
完整文件
公开入口与聚合构建:run.py、pom.xml。context:pom.xml、ContextCacheSuiteTest.java、ProbesApp.java、ContextCounter.java(其余探针类同目录)。tx:pom.xml、TransactionLifecycleTest.java。web:pom.xml、SecurityConfig.java、MockMvcFiltersTest.java、MockMvcMockedUsersTest.java、RealPortTest.java、StandaloneMockMvcTest.java、MockMvcNoFiltersTest.java。slices:pom.xml、WebMvcSliceTest.java、WebMvcSliceMissingServiceProbe.java、JdbcSliceTest.java、RedisSliceTest.java。slice-security:pom.xml、WebMvcSliceSecurityTest.java。client:pom.xml、RestClientErrorPathsTest.java。文件由站点按原路径发布;使用仓库或下载时保留目录关系。
未运行
真实Testcontainers/K8s环境、响应式WebTestClient(mock server与bindToServer真实链路)、JPA/Hibernate切片、@Nested测试类的独立缓存键语义、真实TLS/网络分派(MockMvc场景天然不含)、并发加载同一缓存的线程安全压测。分别归U26/U27及后续票承接,不由本票loopback结果抵扣。
U43 追记:另有独立 JPA 切片实验,使用 H2 验证 repository 映射、测试间回滚与非持久层组件排除;这不改变 U25 原运行记录,也不证明 MySQL 方言。