关于 junit
面向 Java 开发者的 JUnit 5 速查技能,涵盖常见测试模式、注解、反模式和故障排查。
主要功能
- 01JUnit 5 测试模式
- 02Mockito 服务测试
- 03Spring Boot 测试示例
- 04常用注解
- 05反模式与故障排查
适用场景
- 01为 Java 代码编写单元测试
- 02使用 Mockito 测试服务
- 03编写 Spring Boot 控制器或仓库测试
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ claude-dev-suite/ claude-dev-suite --skill junit安装后在 Claude Code 中输入/junit确认已加载。
详细介绍
JUnit 5 - 快速参考
深入了解:使用
mcp__documentation__fetch_docs,并将技术指定为:junit,以获取全面的文档。
不适合使用此技能的情况
- 使用容器进行集成测试 - 使用
testcontainers进行基于 Docker 的测试 - REST API 测试 - 使用
rest-assured进行 HTTP/REST 测试 - Web 端到端测试 - 使用 Selenium 或 Playwright
- JavaScript/TypeScript - 使用
vitest或jest测试 JS/TS - 数据库集成测试 - 与
spring-boot-integration技能结合使用
核心模式
基本测试
@Test
void shouldAddNumbers() {
assertEquals(5, calculator.add(2, 3));
assertThrows(ArithmeticException.class, () -> calculator.divide(10, 0));
}
Mockito + 服务测试
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserServiceImpl userService;
@Test
void shouldCreateUser() {
when(userRepository.save(any())).thenReturn(user);
UserResponse result = userService.create(request);
assertNotNull(result);
verify(userRepository, times(1)).save(any());
}
}
Spring Boot 测试
@SpringBootTest
@ActiveProfiles("test")
class UserServiceIntegrationTest {
@Autowired
private UserService userService;
@MockBean
private UserRepository userRepository;
@Test
void contextLoads() {
assertNotNull(userService);
}
}
控制器测试
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@Test
void shouldReturnUsers() throws Exception {
when(userService.findAll()).thenReturn(users);
mockMvc.perform(get("/api/v1/users"))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].name").value("John"));
}
}
仓库测试
@DataJpaTest
class UserRepositoryTest {
@Autowired
private TestEntityManager entityManager;
@Autowired
private UserRepository userRepository;
@Test
void shouldFindByEmail() {
entityManager.persist(user);
Optional<User> found = userRepository.findByEmail("[email protected]");
assertTrue(found.isPresent());
}
}
常用注解
| 注解 | 用途 |
|---|---|
@Test | 测试方法 |
@BeforeEach | 每次测试前进行设置 |
@Mock | 创建模拟对象 |
@InjectMocks | 注入模拟对象 |
@SpringBootTest | 集成测试 |
@WebMvcTest | 控制器测试 |
@DataJpaTest | 仓库测试 |
反模式
| 反模式 | 缺点 | 解决方案 |
|---|---|---|
| 使用 @SpringBootTest 进行单元测试 | 速度极慢 | 使用 @ExtendWith(MockitoExtension.class) |
| 测试私有方法 | 与实现细节耦合 | 通过公共 API 测试 |
| 未清理模拟对象 | 测试会相互影响 | 使用 @BeforeEach、Mockito.reset() |
| 硬编码测试数据 | 难以维护 | 使用测试数据构建器或工厂 |
| 未验证模拟对象的交互 | 可能导致静默失败 | 使用 verify() 确保方法已调用 |
| 每个测试包含过多断言 | 难以调试 | 每个测试只包含一个逻辑断言 |
| 忽略 @Disabled 测试 | 技术债务会不断累积 | 修复或删除已禁用的测试 |
快速故障排查
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| "测试中出现 NullPointerException" | 未注入模拟对象 | 检查 @Mock 和 @InjectMocks 注解 |
| "Wanted but not invoked" | 未调用方法或参数不正确 | 验证方法调用,检查参数匹配器 |
| 测试耗时过长 | 不必要地使用 @SpringBootTest | 使用 Mockito 进行单元测试 |
| "UnnecessaryStubbingException" | 设置了模拟对象,但未使用 | 删除未使用的 when() 语句 |
| 测试不稳定 | 共享状态或时序问题 | 隔离设置,避免使用 Thread.sleep |
| "未找到测试" | 命名约定错误 | 使用 test* 前缀或 @Test 注解 |
参考文档
评论
支持 Markdown