房山手机网站建设,有关网页设计与网站建设的文章,seo快速排名软件,商家微信下单小程序怎么开通使用trea编写自动测试类#xff0c;发现不能执行#xff0c;之前虽然看过测试类相关的内容#xff0c;但是也只大概知道是怎么样的#xff0c;对测试类代码和原理等没有很清晰的概念#xff0c;只记得使用SpringbootTest注解#xff0c;通过快捷键对每个接口#xff0c;… 使用trea编写自动测试类发现不能执行之前虽然看过测试类相关的内容但是也只大概知道是怎么样的对测试类代码和原理等没有很清晰的概念只记得使用SpringbootTest注解通过快捷键对每个接口方法生成测试代码通过assert断言判断结果是否符合预期可以写一个类似整体的测试方法 一点击便会执行所有的测试方式通过mockMvc模拟一个http请求等。
1.测试依赖
首先需要在项目中添加测试依赖。Spring Boot提供了一个名为spring-boot-starter-test的启动器它包含了常用的测试库如JUnit Jupiter、Spring Test、AssertJ、Hamcrest、Mockito等。
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope
/dependency
2.测试类的基本结构
一个典型的Spring Boot测试类如下所示
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
SpringBootTest
class MyApplicationTests {
Testvoid contextLoads() {}
} SpringBootTest: 这个注解用于告诉Spring Boot这是一个集成测试它会加载整个应用程序上下文。默认情况下它会从当前包及其子包中搜索主配置类例如带有SpringBootApplication的类并启动。
3.单元测试与集成测试
在Spring Boot中测试可以分为两种 单元测试测试单个组件(如一个Service类)通常使用Mockito来模拟依赖 集成测试测试多个组件的交互甚至包括整个应用程序的启动。
单元测试示例
假设有一个CalcuatorService类
Service
public class CalculatorService {public int add(int a, int b) {return a b;}
}
对它的单元测试可以这样写
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class CalculatorServiceTest {
Testvoid testAdd() {CalculatorService calculatorService new CalculatorService();int result calculatorService.add(2, 3);assertEquals(5, result);}
}
集成测试示例
如果你需要测试一个控制器Controller与服务的整合可以使用SpringBootTest启动整个上下文并使用TestRestTemplate或MockMvc进行测试
使用TestRestTemplate
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.ResponseEntity;
import static org.junit.jupiter.api.Assertions.assertEquals;
SpringBootTest(webEnvironment SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HelloControllerIntegrationTest {
Autowiredprivate TestRestTemplate restTemplate;
Testpublic void testHello() {ResponseEntityString response restTemplate.getForEntity(/hello, String.class);assertEquals(Hello, World!, response.getBody());}
}
注意webEnvironment SpringBootTest.WebEnvironment.RANDOM_PORT表示在随机端口启动服务器避免端口冲突。
使用MockMvc
如果不想启动整个服务器而只是想测试Controller层的逻辑可以使用MockMvc
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
SpringBootTest
AutoConfigureMockMvc
public class HelloControllerMockMvcTest {
Autowiredprivate MockMvc mockMvc;
Testpublic void testHello() throws Exception {mockMvc.perform(get(/hello)).andExpect(status().isOk()).andExpect(content().string(Hello, World!));}
}
4.测试配置
使用TestConfiguration
有时候在测试中需要提供特定的bean实现可以使用TestConfiguration注解来定义额外的配置
TestConfiguration
public class TestConfig {Beanpublic MyService myService() {return new MyService() {// 自定义实现};}
}
5.模拟Mocking
使用MockBean和SypBean来模拟Spring容器中的bean MockBean:创建一个Mock对象并替换Spring容器中该类型的bean. SpyBean:创建一个Spy对象会调用真实方法除非被stub.
SpringBootTest
public class UserServiceTest {
Autowiredprivate UserService userService;
MockBeanprivate UserRepository userRepository;
Testpublic void testGetUserById() {// 模拟userRepository的行为when(userRepository.findById(1L)).thenReturn(new User(1L, Alice));
User user userService.getUserById(1L);assertEquals(Alice, user.getName());}
}
6.测试事务
默认情况下Spring Boot的测试是事务性的即每个测试方法执行后都会回滚事务。可以使用Transactional和Rollback来控制。
7.使用TestPropertySource
为了测试可能需要覆盖一些配置属性可以使用TestPropertySource注解
SpringBootTest
TestPropertySource(properties {my.propertyvalue})
public class PropertyTest {// ...
}
8.使用SpringBootTest的classes属性
如果测试类不在主应用程序类的包或其子包下需要显示指定主配置类。
SpringBootTest(classes {Application.class})
public class MyTest {// ...
}
9.使用WebMvcTest进行Controller层单元测试
如果只想测试Controller层可以使用WebMvcTest。它会自动配置MockMvc并只加载相关的Controller和配置。
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.web.servlet.MockMvc;WebMvcTest(HelloController.class)
public class WebMvcTestExample {Autowiredprivate MockMvc mockMvc;Testpublic void testHello() throws Exception {mockMvc.perform(get(/hello)).andExpect(status().isOk()).andExpect(content().string(Hello, World!));}
}
10.使用DataJpaTest进行JPA测试
DataJpaTest用于测试JPA相关的组件它会配置一个内存数据(如H2)和自动配置JPA相关的配置只加载与JPA相关的组件。
DataJpaTest
public class UserRepositoryTest {Autowiredprivate TestEntityManager entityManager;Autowiredprivate UserRepository userRepository;Testpublic void testFindByEmail() {User user new User(testexample.com, password);entityManager.persist(user);User found userRepository.findByEmail(testexample.com);assertEquals(user.getEmail(), found.getEmail());}
}
11.测试启动性能优化
由于SpringBootTest会加载整个应用程序上下文如果测试很多启动速度可能会变慢。为了优化 尽量使用切片测试如WebMvcTest, DataJpaTest来减少加载的组件。 使用MockBean来模拟不需要的依赖。
12.Spring Boot测试中Service空指针问题原因及解决
在Spring Boot测试中调用控制器接口时Service出现空指针异常通常是由于测试环境未正确初始化Spring容器导致依赖注入失败。以下是根本原因和解决方案
问题根源分析
1.容器未启动 测试类缺少SpringBootTest或有效注解 未启用Spring测试支持(JUnit5需ExtendWith(SpringExtension.class))
2.依赖未注入 控制器中的Autowired Service 未成功注入 测试类直接创建控制器实例而非从容器获取
3.作用域问题 使用了new Controller() 而非注入的Bean 未使用MockBean处理依赖
方案一使用WebMvcTest进行切片测试(推荐)
WebMvcTest(UserController.class) // 只加载Web层组件
class UserControllerTest {AutowiredMockMvc mockMvc;MockBean // 关键模拟Service避免空指针UserService userService; Testvoid getUser_shouldReturn200() throws Exception {// 设置Mock行为when(userService.findById(anyLong())).thenReturn(new User(1, Test User));// 模拟HTTP请求mockMvc.perform(get(/users/1)).andExpect(status().isOk()).andExpect(jsonPath($.name).value(Test User));}
}
方案二完整上下文测试SpringBootTest
SpringBootTest(webEnvironment WebEnvironment.RANDOM_PORT)
class IntegrationTest {AutowiredTestRestTemplate restTemplate; // 自动处理URLMockBean // 仍需要Mock以避免真实依赖UserService userService;Testvoid testUserEndpoint() {when(userService.findById(1L)).thenReturn(new User(1, Mock User));ResponseEntityUser response restTemplate.getForEntity(/users/1, User.class);assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);assertThat(response.getBody().getName()).isEqualTo(Mock User);}
}
关键注意事项
1.依赖模拟原则
//正确方式-通过容器注入
Autowired
private UserController controller;//从容器获取//错误方式-导致空指针
private UserController controller new UserController();
2.层级关系图
graph TDA[测试类] --|Autowired| B[MockMvc]A --|MockBean| C[UserService]D[UserController] --|Autowired| CB --|调用| D
特殊场景处理 Lazy初始化导致空指针
MockBean(lazyInit true) // 延迟初始化避免早期依赖问题
ExternalService externalService; Bean冲突
SpringBootTest(properties spring.main.allow-bean-definition-overridingtrue) 自定义配置
TestConfiguration
static class TestConfig {BeanPrimaryUserService testUserService() {return mock(UserService.class);}
}
调试步骤 检查测试类是否有SpringBootTest或WebMvcTest 确认是否添加了MockBean或SpyBean用于Service 在测试方法开头添加调试
BeforeEach
void setup(ApplicationContext context) {// 检查Controller是否被容器管理assertThat(context.getBean(UserController.class)).isNotNull(); // 检查Service是否被注入assertThat(context.getBean(UserController.class).getService()).isNotNull();
}
4.检查控制器是否使用Autowired注入Service
src/main/java → 源码目录
src/main/resources → 资源目录
src/test/java → 测试目录 IDEA的目录标记仅用于IDE内部优化Maven构建时完全依赖pom.xml和标准目录结构忽略IDE标记 若手动创建非标准目录如src/config需在pom.xml中显式配置资源路径
buildresourcesresourcedirectorysrc/config/directory/resource/resources
/build
2.idea MarkDirectory as说明
使用trea编译器生成测试代码由于该项目之前没写过测试代码都是通过postman进行测试所以新建了测试类的文件夹以及目录然后到idea中进行测试发现新增的类没有被识别无法编译通过 idea的MarkDirectory as Test Sources Root功能解决问题。
一目录标记的核心功能
目的明确目录在项目中的角色控制其参与编译索引和资源处理的行为
二各目录类型详解
1.Source Root(源码根目录 标识目录图标变为蓝色src/main/java 典型示例。 作用存放项目核心源码目录内代码会被编译并加入classpath 使用场景 src/main/java等核心代码目录
2.Test Sources Root(测试源码目录) 标识目录图标变为绿色src/test/java 典型示例。 作用 存放单元测试、集成测试代码。 测试代码与生产代码分离编译输出到独立目录2**5**。 使用场景JUnit 测试类存放目录。
3.Resources Root(资源根目录 作用存放配置文件如application.yml,静态资源图片模板 构建时自动复制内容到输出目录如target/classes 使用场景SpringBoot项目的配置文件目录
4.Test Resources Root(测试资源根目录 标识与Resource Root类型但专用于测试
5.Exluded(排查目录 作用 停止索引与搜索IDE 不索引内容全局搜索不包含该目录1。 禁止编译不参与编译构建不加入 classpath1**2**。 取消智能提示内部文件无代码补全、错误检查等功能。 使用场景 临时文件/tmp、编译输出/target、日志目录。 第三方库或自动生成代码如 node_modules 取消排除 File → Project Structure → Modules → Sources选中目录后点击 Cancel Exclusion idea的MarkDirectory as 和maven打包有关系吗 构建时以Maven配置为准 Maven遵循约定优于配置原则默认目录结构为 src/main/java → 源码目录
src/main/resources → 资源目录
src/test/java → 测试目录 IDEA的目录标记仅用于IDE内部优化Maven构建时完全依赖pom.xml和标准目录结构忽略IDE标记 若手动创建非标准目录如src/config需在pom.xml中显式配置资源路径 buildresourcesresourcedirectorysrc/config/directory/resource/resources
/build
潜在冲突场景 目录标记错误若将src/main/java误标记为ExcludedIDEA会停止代码提示但Maven仍正常编译因Maven不读取IDE配置 资源未复制若未标记Resources RootIDEA可能无法实时预览资源文件但Maven构建时会按pom.xml复制资源