Quarkus 验证循环¶
在 PR、重大变更之后以及生产环境之前执行。
何时启用¶
- 开始 Quarkus 服务的 Pull Request 之前
- 重大重构或依赖项升级之后
- 在预生产/生产环境之前的预部署验证
- 执行完整构建 → 代码检查 → 测试 → 安全扫描 → 原生编译流水线
- 验证测试覆盖率满足阈值(80% 以上)
- 原生镜像兼容性测试
阶段 1:构建¶
构建失败时停止并修复编译错误。
阶段 2:静态分析¶
Checkstyle、PMD、SpotBugs(Maven)¶
SonarQube(如果已配置)¶
mvn sonar:sonar \
-Dsonar.projectKey=my-quarkus-project \
-Dsonar.host.url=http://localhost:9000 \
-Dsonar.login=${SONAR_TOKEN}
需要处理的常见问题¶
- 未使用的导入或变量
- 复杂方法(高圈复杂度)
- 潜在的 null 指针解引用
- SpotBugs 标记的安全问题
阶段 3:测试 + 覆盖率¶
# 全テスト実行
mvn clean test
# カバレッジレポート生成
mvn jacoco:report
# カバレッジ閾値を強制(80%)
mvn jacoco:check
# またはGradleで
./gradlew test jacocoTestReport jacocoTestCoverageVerification
测试类别¶
单元测试¶
使用模拟依赖项测试服务逻辑:
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock UserRepository userRepository;
@InjectMocks UserService userService;
@Test
void createUser_validInput_returnsUser() {
var dto = new CreateUserDto("Alice", "alice@example.com");
// Panacheのpersist()はvoid — doNothing + verifyを使用
doNothing().when(userRepository).persist(any(User.class));
User result = userService.create(dto);
assertThat(result.name).isEqualTo("Alice");
verify(userRepository).persist(any(User.class));
}
}
集成测试¶
使用真实数据库(Testcontainers)进行测试:
@QuarkusTest
@QuarkusTestResource(PostgresTestResource.class)
class UserRepositoryIntegrationTest {
@Inject
UserRepository userRepository;
@Test
@Transactional
void findByEmail_existingUser_returnsUser() {
User user = new User();
user.name = "Alice";
user.email = "alice@example.com";
userRepository.persist(user);
Optional<User> found = userRepository.findByEmail("alice@example.com");
assertThat(found).isPresent();
assertThat(found.get().name).isEqualTo("Alice");
}
}
API 测试¶
使用 REST Assured 测试 REST 端点:
@QuarkusTest
class UserResourceTest {
@Test
void createUser_validInput_returns201() {
given()
.contentType(ContentType.JSON)
.body("""
{"name": "Alice", "email": "alice@example.com"}
""")
.when().post("/api/users")
.then()
.statusCode(201)
.body("name", equalTo("Alice"));
}
@Test
void createUser_invalidEmail_returns400() {
given()
.contentType(ContentType.JSON)
.body("""
{"name": "Alice", "email": "invalid"}
""")
.when().post("/api/users")
.then()
.statusCode(400);
}
}
覆盖率报告¶
对于详细覆盖率,查看 target/site/jacoco/index.html:
- 全行覆盖率(目标:80% 以上)
- 分支覆盖率(目标:70% 以上)
- 识别未覆盖的重要路径
阶段 4:安全扫描¶
依赖项漏洞(Maven)¶
关于 CVE,查看 target/dependency-check-report.html。
Quarkus 安全审计¶
OWASP ZAP(API 安全测试)¶
docker run -t ghcr.io/zaproxy/zaproxy:stable zap-api-scan.py \
-t http://localhost:8080/q/openapi \
-f openapi
常见安全检查¶
- [ ] 所有密钥都放在环境变量中(不在代码中)
- [ ] 所有端点的输入验证
- [ ] 已配置认证/授权
- [ ] CORS 已正确配置
- [ ] 已配置安全头
- [ ] 使用 BCrypt 对密码进行哈希
- [ ] SQL 注入防护(参数化查询)
- [ ] 公开端点的速率限制
阶段 5:原生编译¶
GraalVM 原生镜像兼容性测试:
# ネイティブ実行ファイルビルド
mvn package -Dnative
# またはコンテナで
mvn package -Dnative -Dquarkus.native.container-build=true
# ネイティブ実行ファイルテスト
./target/*-runner
# 基本スモークテスト実行
curl http://localhost:8080/q/health/live
curl http://localhost:8080/q/health/ready
原生镜像故障排除¶
常见问题:
- 反射:为动态类添加反射配置
- 资源:使用 quarkus.native.resources.includes 包含资源
- JNI:使用原生库时注册 JNI 类
反射配置示例:
阶段 6:性能测试¶
使用 K6 进行负载测试¶
// load-test.js
import http from 'k6/http';
import { check } from 'k6';
export const options = {
stages: [
{ duration: '30s', target: 50 },
{ duration: '1m', target: 100 },
{ duration: '30s', target: 0 },
],
};
export default function () {
const res = http.get('http://localhost:8080/api/markets');
check(res, {
'status is 200': (r) => r.status === 200,
'response time < 200ms': (r) => r.timings.duration < 200,
});
}
运行:
需要监控的指标¶
- 响应时间(p50、p95、p99)
- 吞吐量(请求/秒)
- 错误率
- 内存使用量
- CPU 使用量
阶段 7:健康检查¶
# Liveness
curl http://localhost:8080/q/health/live
# Readiness
curl http://localhost:8080/q/health/ready
# 全ヘルスチェック
curl http://localhost:8080/q/health
# メトリクス(有効な場合)
curl http://localhost:8080/q/metrics
预期响应:
阶段 8:容器镜像构建¶
# コンテナイメージビルド
mvn package -Dquarkus.container-image.build=true
# または特定のレジストリで
mvn package \
-Dquarkus.container-image.build=true \
-Dquarkus.container-image.registry=docker.io \
-Dquarkus.container-image.group=myorg \
-Dquarkus.container-image.tag=1.0.0
# コンテナテスト
docker run -p 8080:8080 myorg/my-quarkus-app:1.0.0
容器安全扫描¶
阶段 9:配置验证¶
# 全設定プロパティをチェック
mvn quarkus:info
# 全設定ソースをリスト
curl http://localhost:8080/q/dev/io.quarkus.quarkus-vertx-http/config
环境特定检查¶
- [ ] 数据库 URL 已按环境配置
- [ ] 密钥已外部化(Vault、环境变量)
- [ ] 日志级别适当
- [ ] CORS 来源已正确配置
- [ ] 已设置速率限制
- [ ] 已启用监控/追踪
阶段 10:文档审查¶
- [ ] OpenAPI/Swagger 文档为最新(
/q/swagger-ui) - [ ] README 中包含设置说明
- [ ] API 变更已文档化
- [ ] 破坏性变更包含迁移指南
- [ ] 配置属性已文档化
OpenAPI 规范生成:
验证清单¶
代码质量¶
- [ ] 构建成功且无警告
- [ ] 静态分析干净(无高/中等级问题)
- [ ] 代码符合团队规范
- [ ] PR 中无注释或 TODO
测试¶
- [ ] 所有测试成功
- [ ] 代码覆盖率 ≥ 80%
- [ ] 使用真实数据库进行集成测试
- [ ] 安全测试成功
- [ ] 性能在可接受范围内
安全¶
- [ ] 依赖项无漏洞
- [ ] 已测试认证/授权
- [ ] 输入验证完整
- [ ] 源代码中无密钥
- [ ] 已设置安全头
部署¶
- [ ] 原生编译成功
- [ ] 容器镜像构建成功
- [ ] 健康检查正常工作
- [ ] 目标环境配置有效
原生镜像¶
- [ ] 原生可执行文件构建成功
- [ ] 原生测试成功
- [ ] 启动时间 < 100ms
- [ ] 内存占用在可接受范围内
自动化验证脚本¶
#!/bin/bash
set -e
echo "=== Phase 1: Build ==="
mvn clean verify -DskipTests
echo "=== Phase 2: Static Analysis ==="
mvn checkstyle:check pmd:check spotbugs:check
echo "=== Phase 3: Tests + Coverage ==="
mvn test jacoco:report jacoco:check
echo "=== Phase 4: Security Scan ==="
mvn org.owasp:dependency-check-maven:check
echo "=== Phase 5: Native Compilation ==="
mvn package -Dnative -Dquarkus.native.container-build=true
echo "=== All Phases Complete ==="
echo "Review reports:"
echo " - Coverage: target/site/jacoco/index.html"
echo " - Security: target/dependency-check-report.html"
echo " - Native: target/*-runner"
CI/CD 集成¶
GitHub Actions 示例¶
name: Verification
on: [push, pull_request]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Set up JDK 21
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'temurin'
- name: Cache Maven packages
uses: actions/cache@v6
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
- name: Build
run: mvn clean verify -DskipTests
- name: Test with Coverage
run: mvn test jacoco:report jacoco:check
- name: Security Scan
run: mvn org.owasp:dependency-check-maven:check
- name: Upload Coverage
uses: codecov/codecov-action@v7
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: target/site/jacoco/jacoco.xml
最佳实践¶
- 在所有 PR 之前运行验证循环
- 在 CI/CD 流水线中自动化
- 立即修复问题,不积累技术债务
- 保持覆盖率在 80% 以上
- 定期更新依赖项
- 定期测试原生编译
- 监控性能趋势
- 文档化破坏性变更
- 审查安全扫描结果
- 按环境验证配置
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 ev/ECC