add-test

GitHub

根据OpenAEV规范为现有功能创建集成测试、单元测及Fixtures,提升代码覆盖率并验证CRUD操作与权限控制。

.github/skills/add-test/SKILL.md OpenAEV-Platform/openaev

Trigger Scenarios

要求添加测试 需要提高测试覆盖率

Install

npx skills add OpenAEV-Platform/openaev --skill add-test -g -y
More Options

Non-standard path

npx skills add https://github.com/OpenAEV-Platform/openaev/tree/main/.github/skills/add-test -g -y

Use without installing

npx skills use OpenAEV-Platform/openaev@add-test

指定 Agent (Claude Code)

npx skills add OpenAEV-Platform/openaev --skill add-test -a claude-code -g -y

安装 repo 全部 skill

npx skills add OpenAEV-Platform/openaev --all -g -y

预览 repo 内 skill

npx skills add OpenAEV-Platform/openaev --list

SKILL.md

Frontmatter
{
    "name": "add-test",
    "description": "Creates tests for an existing feature following OpenAEV patterns: fixture class, composer, integration test with @Nested groups, and optionally unit tests. Use when asked to add tests or improve test coverage."
}

Add Tests

Prerequisites

  • Entity/feature to test
  • Existing service and controller to test against

Procedure

Step 1 — Create or update the Fixture

Location: openaev-api/src/test/java/io/openaev/utils/fixtures/files/

public class {Entity}Fixture {
  public static {Entity} createDefault{Entity}() {
    {Entity} entity = new {Entity}();
    entity.setName("{Entity}-" + RandomStringUtils.random(25, true, true));
    // set required fields
    return entity;
  }
}

Step 2 — Create or update the Composer

Location: openaev-api/src/test/java/io/openaev/utils/fixtures/composers/

  • Extend ComposerBase<{Entity}>
  • Inner Composer with persist(), delete(), get(), withId()

Step 3 — Create the Integration Test

Location: openaev-api/src/test/java/io/openaev/rest/ or api/

Structure:

@TestInstance(PER_CLASS)
@Transactional
@DisplayName("{Feature} API tests")
public class {Feature}ApiTest extends IntegrationTest {
  public static final String URI = "/api/{features}";
  @Autowired private MockMvc mvc;
  @Autowired private {Feature}Composer composer;

  @BeforeEach void setup() { composer.reset(); }

  @Nested @WithMockUser(isAdmin = true) @DisplayName("CRUD operations")
  class CrudOperations {
    @Test @DisplayName("Can create") void given_validInput_should_createEntity() { /* Arrange / Act / Assert */ }
    @Test @DisplayName("Can read") void given_existingId_should_returnEntity() { ... }
    @Test @DisplayName("Can update") void given_existingEntity_should_updateSuccessfully() { ... }
    @Test @DisplayName("Can delete") void given_existingEntity_should_deleteSuccessfully() { ... }
    @Test @DisplayName("Can search") void given_searchInput_should_returnPage() { ... }
  }

  @Nested @WithMockUser(withCapabilities = {...}) @DisplayName("Permission checks")
  class PermissionChecks { ... }
}

Step 4 — (Optional) Lightweight Controller Tests (no entity)

For controllers that don't manage entities (e.g. static endpoints, utility APIs, configuration endpoints):

  • Skip Steps 1 & 2 (no Fixture/Composer needed)
  • Reuse constants from the controller via package-private static imports — never duplicate string literals
  • Test public endpoints without @WithMockUser when @AccessControl(skipRBAC = true) is present
  • Test HTTP-level concerns: status code, content-type, response body, custom headers, cache-control
@TestInstance(PER_CLASS)
@DisplayName("{Feature} API tests")
class {Feature}ApiTest extends IntegrationTest {
  @Autowired private MockMvc mvc;

  @Nested @DisplayName("GET /endpoint")
  class EndpointGroup {

    @Test @DisplayName("Should respond without authentication")
    void given_unauthenticatedRequest_should_respondSuccessfully() throws Exception {
      // Arrange & Act
      var result = mvc.perform(get("/endpoint"));

      // Assert
      result
          .andExpect(status().isOk())
          .andExpect(content().contentTypeCompatibleWith(MediaType.TEXT_PLAIN))
          .andExpect(content().string(EXPECTED_BODY))  // static import from controller
          .andExpect(header().string("Custom-Header", EXPECTED_VALUE));
    }
  }
}

Key rules for lightweight tests:

  • Constants must be static final (package-private) in the controller, imported via static import in the test
  • Group tests by endpoint using @Nested + @DisplayName
  • Always test both authenticated and unauthenticated access when @AccessControl(skipRBAC = true)
  • Test HTTP headers (Cache-Control, custom headers) when the controller sets them explicitly

Step 5 — (Optional) Create Unit Test

For complex service logic:

@ExtendWith(MockitoExtension.class)
class {Feature}ServiceUnitTest {
  @Mock private {Entity}Repository repository;
  @InjectMocks private {Feature}Service service;
  // given_X_should_Y naming + AAA (Arrange/Act/Assert) pattern
}

Step 6 — Verify

mvn test -pl openaev-api -Dtest="{Feature}ApiTest"
mvn jacoco:check

Sub-Skills

Sub-Skill Use when...
TENANT_ISOLATION.md Adding tenant isolation tests (@Nested TenantIsolation) to verify cross-tenant data doesn't leak

Version History

  • 3.260818.1 Current 2026-08-20 12:00

Same Skill Collection

.github/skills/add-contract-output-type/SKILL.md
.github/skills/add-migration/SKILL.md
.github/skills/create-feature-module/SKILL.md
.github/skills/reduce-tx-baseline/SKILL.md
.github/skills/review-code/SKILL.md
.github/skills/review-docs/SKILL.md
.github/skills/review-frontend/SKILL.md
.github/skills/review-migration/SKILL.md
.github/skills/review-multi-tenancy/SKILL.md
.github/skills/review-performance/SKILL.md
.github/skills/review-security/SKILL.md
.github/skills/activate-tenant-table/SKILL.md

Metadata

Files
0
Version
3.260818.1
Hash
bf1b3173
Indexed
2026-08-20 12:00

- 위키
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-25 06:23
浙ICP备14020137号-1 $방문자$