SuperAPI AI Directory

ddd-testing-strategist

Testing & quality

View repository

Updated 10-15 21:48

About this skill

DDD Testing Strategist

DDD testing strategy — from value object unit tests to end-to-end validation across all DDD architectures. Covers the DDD test pyramid, layer-specific test patterns, mock strategies by architecture, Test-Driven Domain Design (TDDD), CI/CD pipeline integration, and N+1 query detection.

Workflow

用户输入 → 场景分类 → 输出测试策略 + 代码模板

Step 1: Classify by user question scenario (Pyramid/AR/Repository/Mock/CQRS/TDDD/CI-CD/Coverage) Step 2: Get the corresponding test template from references Step 3: Adjust Mock strategy by architecture type Step 4: Output code template + CI/CD configuration + coverage target

什么时候用:用户询问 DDD 测试策略、聚合根测试、Repository 测试、Mock 策略、CQRS 测试、TDDD、CI/CD 测试集成时触发。
## Boundary
### ✅ 擅长处理
1. DDD 测试金字塔(60% Domain + 20% Integration + 10% E2E + 10% Architecture)
2. 各层测试策略:Value Object / Aggregate Root / Domain Service / Repository / Application / Adapter
3. 按架构类型差异化测试(Layered / Hexagonal / Clean / COLA / CQRS / Event Sourcing)
4. 测试驱动领域设计(TDDD)方法论
5. Mock 策略选择(Mock Ports / Capture Events / Real DB)
6. CI/CD 三阶段流水线 + N+1 查询检测 + ArchUnit 架构测试
7. 测试覆盖率目标设定 + 分支覆盖率检查
### ⚠️ 需要条件
1. 已有 DDD 项目代码或正在设计领域模型
2. 已有测试框架(JUnit / Mockito / Spring Test / Testcontainers)
3. 理解 DDD 战术模式(Entity / VO / Aggregate / Repository / Domain Event)
### ❌ 超出范围(不适用场景)
1. 非 DDD 项目测试 — 标准测试框架(JUnit / pytest / Jest)
2. 纯前端测试 — Cypress / Playwright / Vitest
3. 性能 / 负载 / 安全测试 — JMeter / k6 / OWASP ZAP
4. 语言特定测试教程 — 概念和模式语言无关
5. 非 DDD 项目的 CI/CD 配置

## Audience

This skill is designed for: **Backend developers** (implementing DDD architectures), **Software architects** (evaluating and selecting patterns), **Tech leads** (reviewing team implementations), and **DDD beginners** (learning domain-driven design fundamentals).

## Rules

1. DDD test pyramid must prioritize Domain layer testing (60% of total tests).
2. Domain layer tests must never mock Domain Services or Aggregate Roots — only mock external ports.
3. Repository integration tests must use Testcontainers with real databases, never mocks.
4. Event Sourcing projects must include event replay and projection tests.
5. Architecture compliance tests (ArchUnit) must run in CI pipeline.

## DDD 测试金字塔
DDD 金字塔与经典金字塔的关键区别:Domain 层(VO + AR + DS)占 **60%**,是测试核心。
     ╱           E2E Tests           ╲       ← 10%
    ╱──────── API Integration ────────╲       ← 10%
   ╱────── Repository Integration ──────╲     ← 10%
  ╱─────── Application Service ─────────╲    ← 10%
 ╱──────── Domain Service Tests ──────────╲   ← 15%
╱────────── Aggregate Root Tests ───────────╲  ← 25%

╱──────────── Value Object Tests ──────────────╲ ← 15%

## 各层测试策略
### ① Value Object 测试(纯函数)
```java
@Test void money_should_prevent_negative_amount() {
    assertThrows(IllegalArgumentException.class, () -> new Money(-1.0, "CNY")); }
@Test void money_add_should_sum_same_currency() {
    assertEquals(new Money(30.0, "CNY"), new Money(10.0, "CNY").add(new Money(20.0, "CNY"))); }

Coverage: construction validation, operation logic, equality comparison, invariants.

② Aggregate Root testing (core business logic)

class OrderPayTest {
    @Test void pay_changes_status_to_paid_when_draft() { ... }
    @Test void pay_emits_orderPaidEvent() { ... }
    @Test void pay_fails_when_already_paid() { ... }
    @Test void pay_fails_when_cancelled() { ... } }

Coverage: independent test class for each state transition → happy path + boundary conditions + invariants + events.

③ Domain Service testing (Mock Repository, Capture Event)

@Test void pricing_service_applies_vip_discount() {
    when(orderRepository.findById(order.getId())).thenReturn(Optional.of(order));
    pricingService.calculatePrice(order.getId());
    assertEquals(new Money(90.0, "CNY"), order.getTotalAmount()); }

Mock principle: Mock only Repository / Gateway (Interface), do not Mock Domain Service or Aggregate Root.

④ Application Service + ⑤ Repository + ⑥ Adapter testing

@Test void place_order_creates_and_saves() {
    var orderId = handler.handle(new PlaceOrderCommand("cust-123", ...));
    assertNotNull(orderId); }
@SpringBootTest @Testcontainers
class OrderRepositoryImplTest {
    @Test void persists_and_retrieves_complete_aggregate() { ... } }
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class OrderControllerTest {
    @Test void post_orders_returns_201() { ... }
    @Test void post_invalid_product_returns_400() { ... } }

App Service: Mock all external ports. Repository: Testcontainers + real DB. Adapter: MockMvc + real DB.

Mock strategy matrix

Test target Repository Gateway EventBus External
Value Object N/A N/A N/A N/A
Aggregate Root N/A N/A Capture N/A
Domain Service Mock Mock Capture Mock
Application Service Mock Mock Mock Mock
Repository Integration Real DB N/A N/A N/A
API Integration Real DB Mock Mock Mock
E2E Real DB Real Real Real
Principle: Domain layer does not need Mock; Mock only interfaces (Ports), do not Mock implementation classes; use Capture pattern for domain events.

Testing differences across architectures

Architecture Testing focus Difference description
Layered Aggregate Root + Repository Full testing of Domain layer (60%+)
Hexagonal Port Mock + Adapter Integration Mocking the interface means mocking the entire external
Clean Entity + UseCase Interactor Mock output ports at the UseCase layer
COLA Domain + App Service Domain has zero dependencies; additionally test CQRS separation
CQRS Command + Query Read Model Use aggregate testing for write model; query views directly for read model
Event Sourcing Event Replay + Projection Aggregate replay testing (mandatory); projection read model testing

Test-Driven Domain Design(TDDD)

Four-step workflow: RED → GREEN → REFACTOR → REPEAT

@Test void tddd_order_should_not_allow_paying_twice() {
    Order order = Order.create(customerId, items);
    order.pay(mockGateway);
    assertThrows(OrderException.class, () -> order.pay(mockGateway)); }
public void pay(PaymentGateway gateway) {
    if (this.status == OrderStatus.PAID) throw new OrderException("Already paid");
    this.status = OrderStatus.PAID;
    addDomainEvent(new OrderPaidEvent(this.getId())); }

Test coverage targets

Layer Target Key coverage points
Value Object ≥ 95% Construction validation, operation logic, equality comparison
Aggregate Root ≥ 95% State transitions (every path), domain events
Domain Service ≥ 90% Cross-entity orchestration, external data computation
Application ≥ 80% Use Case full path + exception paths
Repository ≥ 80% Aggregate integrity, N+1 queries
Adapter (API) ≥ 70% Protocol conversion, error mapping
Recommend prioritizing trackingbranch coverage, Domain layer ≥ 90%.

Gotchas — common pitfalls

  1. Testing only App Service and not Domain — The core of DDD is the Domain layer.
  2. Mocking Domain Service — Domain Service should not be mocked.
  3. Testing only the Happy Path for aggregate roots — Invariant violations and boundary conditions must be covered.
  4. Treating Repository tests as E2E — Repository only verifies persistence.
  5. Forgetting Event Replay testing — The most hidden source of bugs.
  6. Coupling tests to implementation — Test behavior, not internal details.
  7. Not testing domain events — Event publication should be verified for every business method.
  8. Mocking DB instead of using Testcontainers — Always use a real database.
  9. Not testing the Query side in CQRS — Command and Query side strategies are completely different.
  10. Not detecting N+1 queries — Integrate SQL count detection in CI.
  11. Too many E2E tests — Keep only 3-5 key journeys.
  12. Forget ArchUnit — Dependency direction compliance should be checked automatically.

FAQ

Question Answer
Do aggregate root tests need Spring? No. Pure POJO, use JUnit + AssertJ directly.
Should Repository be mocked or use a real DB? Use mocks for Domain Service; use a real DB for Repository.
How do you test the Query side of CQRS? Access the read model directly; no mocking needed.
What is the essential test for Event Sourcing? Event Replay: given an event sequence → replay → verify state.
How do you avoid N+1 queries? Integrate SQLStatementCountValidator.
What is the difference between TDDD and traditional TDD? TDDD uses "domain behavior/state transitions" as the unit.

Keywords

DDD testing, test pyramid, aggregate root test, value object test, domain service test, repository test, application service test, adapter test, CQRS testing, Event Sourcing test, TDDD, mock strategy, Testcontainers, ArchUnit, N+1 test, domain event test, branch coverage, CI/CD testing, integration test, E2E test, event replay test

References

File Purpose
references/testing.md Test pyramid + TypeScript examples for each layer
references/mock-integration-patterns.md Mock implementation + Java integration testing
references/clean-ddd-hexagonal-testing.md Clean/Hexagonal/DDD multi-layer testing
references/unit-testing-strategies.md VO/AR/DS unit testing + state transitions
references/integration-test-strategies.md Repository/API integration testing + N+1
references/cqrs-event-sourcing-testing.md CQRS + ES replay/projection/snapshot testing
references/test-coverage-targets.md Coverage targets + branch coverage + JaCoCo
references/ci-cd-test-stages.md Three-stage CI/CD + GitHub Actions
references/architecture-testing-comparison.md Architecture-specific testing differences + project phase strategy
references/test-driven-domain-design.md TDDD four-step workflow + complete case study

Examples

File Purpose
examples/domain-test-examples.md VO + AR + DS complete testing example
examples/app-adapter-test-examples.md App Service + Adapter + E2E
examples/cqrs-es-test-examples.md CQRS + ES replay/projection/snapshot testing
examples/builder-mock-patterns.md Builder + Mock Repository/EventPublisher
examples/architecture-test-examples.md ArchUnit architecture testing (layering/aggregate isolation)

Security & Safety

This skill is pure documentation. It contains no executable scripts, collects no user data, accesses no external services or networks.

DDD Skills Journey

📍 You are here: ddd-testing-strategist — Step 6 ← Previous: hand off to ddd-domain-designer skill(Install: npx skills add full-stack-skills/ddd-skills --skill ddd-domain-designer). → Next: hand off to ddd-devops-integration skill(Install: npx skills add full-stack-skills/ddd-skills --skill ddd-devops-integration). 🔗 Related: hand off to ddd-code-reviewer skill(Install: npx skills add full-stack-skills/ddd-skills --skill ddd-code-reviewer) | ddd-cqrs-architecture skill(Install: npx skills add full-stack-skills/ddd-skills --skill ddd-cqrs-architecture). 🏠 Home: hand off to ddd-architecture-awesome skill(Install: npx skills add full-stack-skills/ddd-skills --skill ddd-architecture-awesome).