docs(zh-CN): sync Chinese docs with latest upstream changes (#304)

* docs(zh-CN): sync Chinese docs with latest upstream changes

* update

---------

Co-authored-by: neo <neo.dowithless@gmail.com>
This commit is contained in:
zdoc.app
2026-03-03 14:28:27 +08:00
committed by GitHub
parent adc0f67008
commit ada4cd75a3
114 changed files with 11161 additions and 4790 deletions

View File

@@ -1,12 +1,21 @@
---
name: springboot-verification
description: Verification loop for Spring Boot projects: build, static analysis, tests with coverage, security scans, and diff review before release or PR.
description: "Spring Boot项目验证循环构建、静态分析、测试覆盖、安全扫描以及发布或PR前的差异审查。"
origin: ECC
---
# Spring Boot 验证循环
在提交 PR 前、重大变更后以及部署前运行。
## 何时激活
* 为 Spring Boot 服务开启拉取请求之前
* 在重大重构或依赖项升级之后
* 用于暂存或生产环境的部署前验证
* 运行完整的构建 → 代码检查 → 测试 → 安全扫描流水线
* 验证测试覆盖率是否满足阈值
## 阶段 1构建
```bash
@@ -45,6 +54,111 @@ mvn jacoco:report # verify 80%+ coverage
* 总测试数,通过/失败
* 覆盖率百分比(行/分支)
### 单元测试
使用模拟的依赖项来隔离测试服务逻辑:
```java
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock private UserRepository userRepository;
@InjectMocks private UserService userService;
@Test
void createUser_validInput_returnsUser() {
var dto = new CreateUserDto("Alice", "alice@example.com");
var expected = new User(1L, "Alice", "alice@example.com");
when(userRepository.save(any(User.class))).thenReturn(expected);
var result = userService.create(dto);
assertThat(result.name()).isEqualTo("Alice");
verify(userRepository).save(any(User.class));
}
@Test
void createUser_duplicateEmail_throwsException() {
var dto = new CreateUserDto("Alice", "existing@example.com");
when(userRepository.existsByEmail(dto.email())).thenReturn(true);
assertThatThrownBy(() -> userService.create(dto))
.isInstanceOf(DuplicateEmailException.class);
}
}
```
### 使用 Testcontainers 进行集成测试
针对真实数据库(而非 H2进行测试
```java
@SpringBootTest
@Testcontainers
class UserRepositoryIntegrationTest {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine")
.withDatabaseName("testdb");
@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}
@Autowired private UserRepository userRepository;
@Test
void findByEmail_existingUser_returnsUser() {
userRepository.save(new User("Alice", "alice@example.com"));
var found = userRepository.findByEmail("alice@example.com");
assertThat(found).isPresent();
assertThat(found.get().getName()).isEqualTo("Alice");
}
}
```
### 使用 MockMvc 进行 API 测试
在完整的 Spring 上下文中测试控制器层:
```java
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired private MockMvc mockMvc;
@MockBean private UserService userService;
@Test
void createUser_validInput_returns201() throws Exception {
var user = new UserDto(1L, "Alice", "alice@example.com");
when(userService.create(any())).thenReturn(user);
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content("""
{"name": "Alice", "email": "alice@example.com"}
"""))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.name").value("Alice"));
}
@Test
void createUser_invalidEmail_returns400() throws Exception {
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content("""
{"name": "Alice", "email": "not-an-email"}
"""))
.andExpect(status().isBadRequest());
}
}
```
## 阶段 4安全扫描
```bash
@@ -53,10 +167,27 @@ mvn org.owasp:dependency-check-maven:check
# or
./gradlew dependencyCheckAnalyze
# Secrets (git)
# Secrets in source
grep -rn "password\s*=\s*\"" src/ --include="*.java" --include="*.yml" --include="*.properties"
grep -rn "sk-\|api_key\|secret" src/ --include="*.java" --include="*.yml"
# Secrets (git history)
git secrets --scan # if configured
```
### 常见安全发现
```
# Check for System.out.println (use logger instead)
grep -rn "System\.out\.print" src/main/ --include="*.java"
# Check for raw exception messages in responses
grep -rn "e\.getMessage()" src/main/ --include="*.java"
# Check for wildcard CORS
grep -rn "allowedOrigins.*\*" src/main/ --include="*.java"
```
## 阶段 5代码检查/格式化(可选关卡)
```bash