Springboot Verification

affaan-m/ECC/skills/springboot-verification

作者 affaan-mef648e01899ba3e8dc6371642deaaf64b4477775無授權條款275K 個星標收錄於 2026年10月9日更新於 2026年10月9日儲存庫4 天前更新

Run the full Spring Boot verification loop — Maven or Gradle build, SpotBugs, PMD, and Checkstyle static analysis, unit and Testcontainers integration tests with JaCoCo coverage, OWASP dependency and secret scans, and diff review — producing a pass/fail readiness report. Use when preparing a Spring Boot pull request, validating coverage thresholds, or running pre-deploy verification.

AI 產生的概覽

執行 Spring Boot 驗證循環,涵蓋建置、靜態分析、測試、覆蓋率、安全掃描與差異審查。

功能
此技能引導代理對 Spring Boot 專案執行六個階段的驗證循環:Maven 或 Gradle 建置、SpotBugs/PMD/Checkstyle 靜態分析、單元測試與 Testcontainers 整合測試及 JaCoCo 覆蓋率、OWASP 相依性與密鑰掃描、可選的格式化,以及 git diff 審查。它提供單元測試、整合測試與 MockMvc API 測試的範例程式碼。最終產出包含建置、靜態、測試、安全與差異狀態的通過/未通過就緒報告,並列出待修正問題。
適用情境
適用於為 Spring Boot 服務開啟拉取請求之前、重大重構或相依性升級之後,或針對預備環境與正式環境的部署前驗證。也適合驗證測試覆蓋率是否符合門檻。
執行需求
需要一個使用 Maven 或 Gradle 的 Spring Boot 專案,以及相關外掛與工具:SpotBugs、PMD、Checkstyle、JaCoCo、OWASP dependency-check、Testcontainers 與容器執行環境,可選 Spotless 與 git-secrets。相依性解析與容器映像拉取需要網路存取。此技能不附帶指令碼,僅為說明文件。

Spring Boot Verification Loop

Run before PRs, after major changes, and pre-deploy.

When to Activate

  • Before opening a pull request for a Spring Boot service
  • After major refactoring or dependency upgrades
  • Pre-deployment verification for staging or production
  • Running full build → lint → test → security scan pipeline
  • Validating test coverage meets thresholds

Phase 1: Build

bash
mvn -T 4 clean verify -DskipTests# or./gradlew clean assemble -x test

If build fails, stop and fix.

Phase 2: Static Analysis

Maven (common plugins):

bash
mvn -T 4 spotbugs:check pmd:check checkstyle:check

Gradle (if configured):

bash
./gradlew checkstyleMain pmdMain spotbugsMain

Phase 3: Tests + Coverage

bash
mvn -T 4 testmvn jacoco:report   # verify 80%+ coverage# or./gradlew test jacocoTestReport

Report:

  • Total tests, passed/failed
  • Coverage % (lines/branches)

Unit Tests

Test service logic in isolation with mocked dependencies:

java
@ExtendWith(MockitoExtension.class)class UserServiceTest {
  @Mock private UserRepository userRepository;  @InjectMocks private UserService userService;
  @Test  void createUser_validInput_returnsUser() {    var dto = new CreateUserDto("Alice", "[email protected]");    var expected = new User(1L, "Alice", "[email protected]");    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", "[email protected]");    when(userRepository.existsByEmail(dto.email())).thenReturn(true);
    assertThatThrownBy(() -> userService.create(dto))        .isInstanceOf(DuplicateEmailException.class);  }}

Integration Tests with Testcontainers

Test against a real database instead of H2:

java
@SpringBootTest@Testcontainersclass 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", "[email protected]"));
    var found = userRepository.findByEmail("[email protected]");
    assertThat(found).isPresent();    assertThat(found.get().getName()).isEqualTo("Alice");  }}

API Tests with MockMvc

Test controller layer with full Spring context:

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", "[email protected]");    when(userService.create(any())).thenReturn(user);
    mockMvc.perform(post("/api/users")            .contentType(MediaType.APPLICATION_JSON)            .content("""                {"name": "Alice", "email": "[email protected]"}                """))        .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());  }}

Phase 4: Security Scan

bash
# Dependency CVEsmvn org.owasp:dependency-check-maven:check# or./gradlew dependencyCheckAnalyze
# Secrets in sourcegrep -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

Common Security Findings

# Check for System.out.println (use logger instead)grep -rn "System\.out\.print" src/main/ --include="*.java"
# Check for raw exception messages in responsesgrep -rn "e\.getMessage()" src/main/ --include="*.java"
# Check for wildcard CORSgrep -rn "allowedOrigins.*\*" src/main/ --include="*.java"

Phase 5: Lint/Format (optional gate)

bash
mvn spotless:apply   # if using Spotless plugin./gradlew spotlessApply

Phase 6: Diff Review

bash
git diff --statgit diff

Checklist:

  • No debugging logs left (System.out, log.debug without guards)
  • Meaningful errors and HTTP statuses
  • Transactions and validation present where needed
  • Config changes documented

Output Template

VERIFICATION REPORT===================Build:     [PASS/FAIL]Static:    [PASS/FAIL] (spotbugs/pmd/checkstyle)Tests:     [PASS/FAIL] (X/Y passed, Z% coverage)Security:  [PASS/FAIL] (CVE findings: N)Diff:      [X files changed]
Overall:   [READY / NOT READY]
Issues to Fix:1. ...2. ...

Continuous Mode

  • Re-run phases on significant changes or every 30–60 minutes in long sessions
  • Keep a short loop: mvn -T 4 test + spotbugs for quick feedback

Remember: Fast feedback beats late surprises. Keep the gate strict—treat warnings as defects in production systems.

來源與署名

來源:affaan-m/ECC位於skills/springboot-verification提交ef648e0

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架