ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Spring Boot测试实战:从依赖配置到MockMvc与Testcontainers的完整指南

Spring Boot测试实战:从依赖配置到MockMvc与Testcontainers的完整指南 1. 从sringboot这个拼写说起Spring Boot测试到底在测什么先别笑这个标题原样就是sringboot测试s-r-i-n-g-b-o-o-t少了个p。我见过不少开发者在IDEA里、在搜索引擎里、甚至在简历上把Spring Boot拼错这其实是个很有意思的隐喻——很多人对Spring Boot测试的认知也像这个拼写一样看着差不多真较真起来全是细节。Spring Boot测试是个特别容易看着会、上手懵的领域。你问一个写过两年Java的人Spring Boot项目怎么加测试他能说上来加个spring-boot-starter-test依赖然后写个SpringBootTest注解把上下文拉起来跑一下mvn test看到绿色就收工。但真到了生产项目里这套流程会遇到一堆问题测试启动时间越来越长数据库连接怎么隔离文件上传接口怎么用RestTemplate传MultipartFileSpring Boot版本升到3.x之后CGLIB代理和Mockito兼容性出幺蛾子签名认证的接口在测试环境里怎么绕过去……这些才是真正决定测试到底能不能落地的关键。这篇文章就从这些真实问题切入把我自己踩过的坑、试过的方法、最终沉淀下来的一套可复用方案完整梳理一遍。适合这几类人看刚接触Spring Boot测试想建立完整认知的新人写了几个测试但总觉得不得要领的进阶者以及被版本太高RestTemplate传文件签名认证这类具体问题卡住、想找现成解决方案的人。先说结论性的一句话Spring Boot测试的核心价值不是能跑通而是能快速、稳定、低维护地跑通。后面所有内容都围绕这句话展开。2. 测试环境搭建依赖选型与配置隔离这两步决定了后面90%的体验2.1 一个spring-boot-starter-test里到底有什么Spring Boot的测试依赖设计得很全家桶——你只要在pom.xml里加一个spring-boot-starter-test它会把下面这些帮你打包好JUnit 5junit-jupiter测试框架本体Test、BeforeEach、DisplayName这些都从它来Spring Test与Spring Boot Test提供SpringBootTest、MockBean、TestRestTemplate这些核心注解和工具类AssertJ流式断言库assertThat(result).isEqualTo(...)这种写法比JUnit原生断言可读性强太多MockitoMock对象的标准库后面讲Service层隔离测试全靠它Hamcrest老牌匹配器库AssertJ没进Spring Boot测试依赖之前它才是默认JSONassert专门比较JSON结构的断言库测接口返回体时特别方便Json Path配合MockMvc做JSON字段级校验。这个全家桶设计有一个好处你不用自己去操心版本兼容性spring-boot-starter-parent统一管理版本号。但也有个坏处——很多人只知道加了依赖就能写测试从来不看具体引入了什么导致后面出问题时一脸懵。我建议你至少花十分钟点开Maven面板看看spring-boot-starter-test的依赖树里到底有哪些包这比看十篇教程都管用。2.2 测试配置隔离别让你的测试连到生产数据库这是新手最容易踩的坑。很多人写完SpringBootTest启动测试一看连接的是本地开发数据库甚至有人连到过测试环境的数据库。后果轻则跑完测试产生一堆脏数据重则把测试环境的表结构或数据弄坏。正确的做法是测试配置独立。我常用的方案是application-test.yml配合ActiveProfiles(test)注解spring: datasource: url: jdbc:h2:mem:testdb;MODEMySQL;DB_CLOSE_DELAY-1 driver-class-name: org.h2.Driver username: sa password: jpa: hibernate: ddl-auto: create-drop show-sql: true然后在测试类上加SpringBootTest ActiveProfiles(test) class UserServiceTest { // ... }这样每次测试启动都会创建一个全新的内存数据库用完即焚不会污染任何真实环境。你可能会问为什么用H2而不是直接用MySQL的测试库原因有三点。第一H2是内存数据库每次测试启动秒开而连远程MySQL光握手就要几百毫秒一百个用例跑下来差距是分钟级的第二测试数据完全隔离不会出现同一个测试跑两遍结果不一样这种尴尬第三H2支持MySQL兼容模式MODEMySQL大部分SQL语法都能直接跑过。H2当然也有局限。如果项目里用了复杂的JSON字段、全文索引、特定存储引擎的语法H2可能解析不了。这种时候我建议引入Testcontainers用Docker起一个真正的MySQL容器来测。关于Testcontainers后面专门说这里先记住原则测试环境必须自包含绝不依赖开发者的本机配置更不能依赖远程服务。2.3 配置加载顺序为什么你的MockBean有时候不生效测试配置第二个常见坑是加载顺序。Spring Boot的配置优先级是测试类上的注解ActiveProfiles、TestPropertySource 测试目录下的application-test.yml 主配置application.yml。这个顺序决定了你能不能在测试里覆盖某个生产配置值。举个例子生产环境里有个签名认证的开关app: security: signature-verify-enabled: true测试环境你想关掉它直接在application-test.yml里写false就能覆盖。但如果这个配置是写在某个Configuration类里的Value注入而那个类又用了ConditionalOnProperty那你就得用TestPropertySource显式指定属性SpringBootTest ActiveProfiles(test) TestPropertySource(properties app.security.signature-verify-enabledfalse) class SignatureTest { // ... }这种细节型坑最容易让人抓狂。我自己的经验是写测试之前第一件事不是写测试用例而是先想清楚这个测试要启动哪些配置、屏蔽哪些配置。3. 从慢到快的测试分级WebMvcTest、DataJpaTest和SpringBootTest该怎么选3.1 全量启动的SpringBootTest是重量级武器不该是默认选项很多人写测试有一种力大砖飞的思路——不管测什么直接SpringBootTest把整个Spring上下文拉起来。这个注解会加载完整的应用上下文包括所有Configuration、Component、Service、Repository还会执行所有的CommandLineRunner和ApplicationRunner。后果就是测试启动越来越慢。我见过一个中等规模的项目SpringBootTest启动一次要20到30秒两百个用例跑一遍要将近一个小时。到了这个地步团队成员就会本能地逃避运行测试测试也就名存实亡了。正确的思路是分级测试。Spring Boot从1.4开始就支持切片测试Slice Test只加载你需要的那个层大幅缩短启动时间。3.2WebMvcTest只测Controller层启动速度秒级WebMvcTest只加载Web层相关的BeanController、ControllerAdvice、过滤器、拦截器等。Service和Repository层不加载这也是为什么它通常要配合MockBean来mock掉Service依赖。WebMvcTest(UserController.class) class UserControllerTest { Autowired private MockMvc mockMvc; MockBean private UserService userService; Test DisplayName(GET /users/{id} 返回用户信息) void getUserById() throws Exception { User user new User(1L, 张三, zhangsanexample.com); when(userService.getUserById(1L)).thenReturn(user); mockMvc.perform(get(/users/1)) .andExpect(status().isOk()) .andExpect(jsonPath($.name).value(张三)) .andExpect(jsonPath($.email).value(zhangsanexample.com)); } }这个测试启动只加载Web层一秒钟内就能起来。跑得越快开发时才越愿意随手运行这是测试能坚持下去的前提。WebMvcTest有个需要留意的点它默认会加载spring-security-test如果项目里有Spring Security会自动应用安全过滤链。如果你的接口有权限控制测试时需要额外处理认证。最简单的做法是用WithMockUser注解Test WithMockUser(username admin, roles {ADMIN}) void deleteUser() throws Exception { mockMvc.perform(delete(/users/1)) .andExpect(status().isNoContent()); }3.3DataJpaTest只测Repository层自动回滚事务DataJpaTest同理只加载JPA相关的组件默认使用内嵌数据库H2默认开启事务回滚——也就是说每个测试方法跑完数据自动回滚测试之间互不影响。DataJpaTest class UserRepositoryTest { Autowired private UserRepository userRepository; Test DisplayName(根据邮箱查询用户) void findByEmail() { User user new User(李四, lisiexample.com); userRepository.save(user); OptionalUser result userRepository.findByEmail(lisiexample.com); assertThat(result).isPresent(); assertThat(result.get().getName()).isEqualTo(李四); } }这里有个性能优化技巧如果你的Repository测试很多可以在类上加Transactional保持默认回滚行为同时用DirtiesContext控制上下文缓存。Spring Test框架会缓存上下文如果多个测试类的切面配置完全一样它们会共用一个ApplicationContext不会重复启动。3.4SpringBootTest的正确使用场景那SpringBootTest到底什么时候该用我的判断标准是当你需要验证组件之间的真实协作时才值得用全量启动。典型的场景有验证Transactional行为在真实ServiceRepository链路上是否正确验证定时任务、消息监听器等启动即运行的后台组件验证配置类是否正确装配比如EnableScheduling、EnableAsync这种全局开关端到端的接口测试从HTTP请求到数据库落库全链路验证。如果是这类需求宁可少写几个SpringBootTest也别把它当成唯一武器。一个维护良好的测试套件应该像金字塔底部大量快速的单元/切片测试中间适量的接口级集成测试顶部少量全链路测试。反过来就是灾难。4. 集成测试实战MockMvc、文件上传、签名认证这些接口级问题一次性说透4.1 MockMvc完整姿势GET、POST、响应断言、中文乱码处理集成测试里最常用的工具就是MockMvc。它不启动真实服务器而是通过Spring MVC的DispatcherServlet直接分发请求所以比真正的HTTP调用快得多。MockMvc有两种构建方式。一种是上面WebMvcTest里的自动注入版另一种是在SpringBootTest里手动构建SpringBootTest AutoConfigureMockMvc class OrderControllerIntegrationTest { Autowired private MockMvc mockMvc; Test void createOrder() throws Exception { OrderCreateRequest request new OrderCreateRequest(1001L, 299.99, 2); mockMvc.perform(post(/orders) .contentType(MediaType.APPLICATION_JSON) .content(new ObjectMapper().writeValueAsString(request))) .andExpect(status().isCreated()) .andExpect(header().string(Location, /orders/1)) .andExpect(jsonPath($.total).value(599.98)); } }这里有个细节用MockMvc测试POST JSON时content(...)一定要配合contentType(MediaType.APPLICATION_JSON)否则Spring MVC无法正确解析请求体。另外jsonPath断言时如果返回的JSON有中文要留意字符编码——测试环境里最常见的乱码源头是server.servlet.encoding.charset未配置或者被覆盖可以在application-test.yml里显式指定UTF-8。4.2 文件上传接口MultipartFile用RestTemplate传输的深坑与解法热搜词里有springboot中mutipart如何用resttemplate传这是个高频问题我展开讲讲。先说背景。如果你在集成测试里想模拟真实HTTP请求而不是用MockMvc比如调了一个第三方服务或者测试一个真正启动在随机端口上的Spring Boot应用你就得用RestTemplate。然后你发现要传一个MultipartFile字段直接MultiValueMap往里塞FileSystemResource是能跑通的RestTemplate restTemplate new RestTemplate(); MultiValueMapString, Object body new LinkedMultiValueMap(); body.add(file, new FileSystemResource(/path/to/file.txt)); body.add(description, 测试文件); HttpHeaders headers new HttpHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA); HttpEntityMultiValueMapString, Object requestEntity new HttpEntity(body, headers); ResponseEntityString response restTemplate.exchange( http://localhost:8080/upload, HttpMethod.POST, requestEntity, String.class );但如果你手里是一个内存中的MultipartFile对象比如测试代码里Mock出来的直接往body.add()里塞MultipartFile是不行的——RestTemplate的HttpMessageConverter不认识它会报no suitable HttpMessageConverter。解法是手动构造一个ByteArrayResource来包装文件字节public class ByteArrayMultipartFileResource extends ByteArrayResource { private final String filename; public ByteArrayMultipartFileResource(byte[] byteArray, String filename) { super(byteArray); this.filename filename; } Override public String getFilename() { return this.filename; } }这个覆写是关键。ByteArrayResource默认不返回文件名而RestTemplate的MultipartFormHttpMessageConverter在写入part时需要从resource的getFilename()获取文件名不覆写就会丢文件名接口那边收到的是无名文件。使用方式byte[] fileBytes Files.readAllBytes(Paths.get(/path/to/file.txt)); body.add(file, new ByteArrayMultipartFileResource(fileBytes, file.txt));这个坑我踩过一次之后专门封装了一个工具方法放在测试公共包里面项目里所有人都直接调。建议你也这么做把这种测试基建沉淀下来省得每人重新造一遍轮子。4.3 签名认证接口怎么测关闭、绕过、还是带着签名测接口签名认证是另一个常见痛点。生产环境里两个系统之间调用通常要做签名MD5、HMACSHA256、RSA这些比如热搜词里的springboot 签名认证。测试的时候这玩意儿特别烦每次都要构造合法签名还涉及时间戳偏移、随机nonce这些动态参数一旦测试代码写得不够好case就会时好时坏。我的经验分三个层次按场景选择层次一如果能关就关掉。如果你测试的是业务逻辑而非签名机制本身用前面说的TestPropertySource把签名校验开关关掉最省事。前提是项目代码里做签名校验时用了ConditionalOnProperty之类的开关而不是硬编码在过滤器里。如果硬编码那就得用层次二或三。层次二测试包里单独写一个签名工具。把生产环境生成签名的逻辑复制一份到测试源码目录src/test/java测试时先调用它生成合法签名再加到请求上。这样能验证签名校验逻辑本身没被破坏代价是维护两份签名代码签名算法升级时容易漏。层次三用Mock或AOP拦截。在测试配置里单独定义一个TestConfiguration把签名校验过滤器替换成一个直接放行的过滤器。这种方式最优雅不碰生产代码也不维护双份签名逻辑TestConfiguration public class BypassSignatureConfig { Bean Primary public SignatureVerifier signatureVerifier() { return new SignatureVerifier() { Override public boolean verify(HttpServletRequest request) { return true; } }; } }然后在测试类上通过Import(BypassSignatureConfig.class)引入。Primary注解确保测试上下文中优先使用这个放行版本。我个人倾向的排序是能关就关 用TestConfiguration替换 维护签名工具。第一种最快第二种最稳第三种能顺带验证签名链路但维护成本高。你要根据团队实际情况选没有标准答案。5. 版本兼容性Spring Boot 3.x、CGLIB代理、Mockito这些报错三兄弟怎么一次解决5.1 Spring Boot版本太高到底高在哪热搜词里有springboot版本太高和idea 2026 怎么配置springboot服务 编辑配置数据 比如启动端口,这两条放一起看特别有画面感——大概率是某个新人在新版本环境里配旧项目的经典场景。Spring Boot的版本演进里Spring Boot 2.x到3.x是一次大断裂不是因为版本号跳得大而是因为底层基础换了Java基线从8升到17你的pom.xml里若java.version还写着1.8Spring Boot 3.x直接起不来javax.换成jakarta.所有import javax.persistence.*、import javax.validation.*要全部改成jakarta.*Spring Security的lambda风格配置http.authorizeRequests().antMatchers(...)这种旧写法全部废弃换成authorizeHttpRequests().requestMatchers(...)spring.factories废弃自动配置注册方式大改第三方starter如果没跟上就失效。版本太高的本质往往不是Spring Boot本身出问题而是你的代码和它周围的生态还停留在上一个时代。5.2 CGLIB代理与Mockito为什么MockBean在3.x里强调默认使用CGLIB热搜词里有springboot默认使用cglib代理这是个基础但同时是测试相关的坑点。Spring Boot默认开启spring.aop.proxy-target-classtrue也就是AOP代理一律使用CGLIB而不是JDK动态代理。JDK动态代理只能代理接口CGLIB通过字节码生成子类可以代理具体类。这本身是好事——你不用强制类实现接口了。但放在测试里就有个经典翻车当你用MockBean去Mock一个普通Service类时如果这个Service内部有Autowired字段或Transactional方法Mockito生成的代理可能和CGLIB代理打架。具体表现是测试启动时抛异常报BeanNotOfRequiredTypeException或者ClassCastException。解决思路分两种。大多数情况下把被Mock的Bean声明在测试类里并用MockBean就可以——Spring Boot测试框架会专门处理代理替换。但如果你的Service同时被Transactional和AOP切面包裹且切面内部有Autowired依赖MockBean替换时那些依赖是空的业务代码一执行就到NPE。这种情况我建议放弃MockBean改用SpringBootTest加真实Bean或者把依赖的类单独Mock掉。总之遇到代理怪问题先别急着改代码理清楚谁代理了谁、Mock替换的是哪个Bean才是关键。5.3 Spring Boot 3.x升级后的测试适配清单如果你正打算从Spring Boot 2.x升到3.x或者刚升完测试跑不起来下面这份清单可以照着查问题现象可能原因处理方式测试编译报javax.*不存在依赖库还没适配Jakarta升级所有starter到兼容3.x的版本检查自定义代码里的javax导入MockBean有废弃提示Spring Boot 3.4开始推荐MockitoBean优先用MockitoBean需要时再降级用MockBeanMockMvc里antMatchers报错Spring Security 6.0移除了旧API改为requestMatchers并把and()链式风格重写启动报Invalid value type for attribute factoryBeanObjectTypeCGLIB代理类与Mockito代理类型冲突升级Mockito到5.x确认spring.aop.proxy-target-class设置时区、LocalDateTime序列化结果不对3.x默认jackson版本对JavaTime模块处理有变检查spring.jackson配置显式指定时间格式这条清单是我自己升级项目时一条条踩出来整理的不能覆盖所有情况但覆盖了80%的常见翻车点。最重要的是升级前先做一次依赖树审计把所有间接依赖的版本列出来看有没有明显的不兼容信号。6. 模拟外部中间件与真实数据库从H2到Testcontainers的进阶之路6.1 为什么H2不是万能的前面提到H2方便但真实项目里有个尴尬你在H2上跑得好好的SQL到了MySQL或PostgreSQL上报错。最常见的就两件事一是方言差异。H2的MySQL兼容模式再像MySQL也只是像。JSON字段类型、ON DUPLICATE KEY UPDATE这种特定语法、甚至注释里的特殊写法都可能成为测试通过、上线报错的隐患。二是镜像逻辑偏差。如果你在Repository里写了Query的复杂SQL靠H2根本验证不了因为执行计划、索引行为、锁和事务隔离级别的表现完全不一样。这时候Testcontainers是更好的选择。它的思路很简单测试启动时用Docker起一个真实的数据库容器测试结束关闭容器。你用的是真数据库就不再存在H2能过、MySQL挂的差异问题。6.2 Testcontainers集成示例一条命令起一个MySQL引入Testcontainers的方式也简单。先加依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-testcontainers/artifactId scopetest/scope /dependency dependency groupIdorg.testcontainers/groupId artifactIdmysql/artifactId scopetest/scope /dependency dependency groupIdorg.testcontainers/groupId artifactIdjunit-jupiter/artifactId scopetest/scope /dependency然后定义一个Testcontainers的测试基类或者配置类Testcontainers SpringBootTest ActiveProfiles(testcontainers) class OrderRepositoryTest { Container static MySQLContainer? mysql new MySQLContainer(mysql:8.0) .withDatabaseName(testdb) .withUsername(test) .withPassword(test); DynamicPropertySource static void configureDatabase(DynamicPropertyRegistry registry) { registry.add(spring.datasource.url, mysql::getJdbcUrl); registry.add(spring.datasource.username, mysql::getUsername); registry.add(spring.datasource.password, mysql::getPassword); } // 测试代码... }DynamicPropertySource会在Spring上下文初始化前动态注入数据源配置这样application-testcontainers.yml里就可以留空或者只放非敏感配置。测试跑起来Testcontainers会自动拉取MySQL 8.0容器镜像、启动、初始化数据库测试结束自动清理。这个方案唯一的缺点是依赖Docker。本地环境、CI环境都得有Docker可用。如果你们团队有人不装Docker这个方案就跑不起来。我的折中做法是日常开发用H2跑快速反馈CI/CD里用Testcontainers跑完整回归。两者配合兼顾速度和真实度。6.3 不仅仅是数据库ActiveMQ、Flink等中间件的测试思路热搜词里有springboot整合activemqspringboot整合flink这些框架的测试思路其实殊途同归。核心原则就一条能mock就mock能内嵌就内嵌能容器化就容器化。ActiveMQ可以用内嵌的ActiveMQEmbeddedBrokerBrokerService在测试JVM里起一个消息中间件。生产者发消息、消费者收消息全链路都是真实的但没有外部依赖。做法是在BeforeAll里启动BrokerAfterAll关闭。FlinkFlink本身提供MiniClusterWithClientCluster可以在本地模拟一个完整的Flink集群JobManager TaskManager。测试时把StreamExecutionEnvironment替换成MiniCluster提供的StreamExecutionEnvironment之后逻辑跟生产代码几乎一致。唯一要注意的是并行度调低比如设为1或2否则测试资源开销会比较大。Redis、Kafka优先Testcontainers。Redis的GenericContainer(“redis:7”)、Kafka的KafkaContainer网上的示例一搜一大把不谈。这里要强调一个理念集成测试里起真实中间件是有代价的每个中间件都会拖慢测试启动时间。所以要有节奏感——单元测试和切片测试用Mock集成测试按需起中间件把所有中间件都起一遍的全链路测试只保留一条冒烟链路。7. Spring Boot测试的高频面试题与团队落地心得7.1 这些Spring Boot测试问题面试里真的会问热搜词里有springboot面试题自动化测试框架pytest,说明很多人通过面试题来学习Spring Boot测试。我结合自己面试别人的经验挑几个高频考点说说。第一个SpringBootTest和WebMvcTest有什么区别这是最基础的区分题。回答要点是SpringBootTest加载完整上下文适合集成测试WebMvcTest只加载Web层适合Controller的单元/切片测试。如果能补充一句切片测试会让测试套件跑得更快所以在团队里我更推荐优先用切片测试会显得你有实战意识。第二个MockBean的实现原理MockBean在Spring Boot测试框架里通过MockitoPostProcessor实现——它会在BeanDefinition准备阶段把目标Bean替换成一个Mockito mock并注册到ApplicationContext。如果Bean是CGLIB代理就要额外处理代理链。这个问题能展开讲很多回答时抓住替换Bean定义这个核心即可。第三个测试时数据库事务回滚是怎么实现的答案是Transactional在测试类上的特殊语义Spring Test框架会把每个测试方法包在一个事务里测试结束回滚所以测试不会污染数据库。切面JPA测试默认有这个行为SpringBootTest默认没有需要手动加Transactional。很多人不知道这个区别答出来就是加分项。第四个怎么保证测试的随机性比如测试里依赖当前时间、随机数、UUID怎么保证可重复推荐方案是抽象Clock接口生产环境注入真实Clock.systemDefaultZone()测试环境注入固定时间的Clock.fixed(...)。这个模式能延伸到IdGenerator、RandomGenerator等所有不可控的依赖上是测试设计能力的直接体现。第五个pytest、Appium这些和Spring Boot测试什么关系pytest是Python生态的自动化测试框架Appium是移动端UI自动化它们跟Spring Boot的关系在于全链路测试策略——后端服务测试Spring Boot Test只负责验证服务逻辑UI层和端到端的验证由专门的测试工程师用这些工具去补。知道这个分工说明你有全局视野。7.2 让团队真的愿意写测试而不是把测试当成KPI最后说点务实的。我见过很多项目测试覆盖率指标很好看但实际价值接近于零——测试断言写得宽泛assertThat(result).isNotNull()结束跑起来永远绿但覆盖不了任何回归风险。要让测试真正发挥作用我的经验是四条第一让测试成为开发过程的一部分而不是发布前的临时动作。写完一个Service方法顺手把测试写完再跑一遍这个习惯一旦养成你写代码时就会主动考虑可测性代码质量会跟着上去。第二测试命名要有业务语义。testAddUser这种名字等于没写。用DisplayName写清楚当用户邮箱已存在时注册接口返回409三个月后回来看还能一眼明白当时在验证什么。第三别追求覆盖率数字追求关键路径覆盖。登录、下单、支付、退款这类核心链路的每个分支都要测到边缘的getter/setter坚决不测。覆盖率报告用来发现有没有完全没测过的模块而不是用来跟别人比数字。第四维护测试的成本预算。如果一个测试类每次跑要花几十秒用的人也少它的维护动力就会下降。定期清理慢测试、合并重复测试比无限增加新测试更重要。7.3 把这些测试思路扩展到一个完整项目中如果你想用一篇博文的篇幅把上面所有内容落进一个实战项目我建议这样规划一个基于Spring Boot 3.x的简单商品管理后端对应热词中的基于springboot vue商品管理系统包含用户注册登录、商品CRUD、文件上传、消息推送。然后按这套结构安排测试注册登录接口WebMvcTestMockBean覆盖成功、密码错误、参数缺失三个分支商品CRUD服务DataJpaTest 内存数据库覆盖Repository查询逻辑文件上传接口SpringBootTestMockMvc用MockMultipartFile模拟文件再补一个用RestTemplate传MultipartFile的真实HTTP场景消息推送SpringBootTest 内嵌ActiveMQ验证生产者发消息后消费者能收到。这套组合下来既能覆盖核心逻辑又不会让整个测试套件慢到没人想跑。更重要的是每块测试的为什么这么设计你心里都有数。回到开头那个拼写错误。有人把Spring Boot拼成sringboot是因为对框架本身不熟但如果你把Spring Boot测试只理解成加个依赖、写个SpringBootTest那跟拼错字母本质上是一回事——形似而神不至。真正有价值的东西藏在如何选测试级别、如何隔离环境、如何绕开版本陷阱、如何让测试持续产生价值这些细节里。希望这篇梳理能帮你把这些细节一次补齐。
返回列表