smithery/hzeroxium

java-testing-integration

Design and implement deterministic integration tests (DB/queue/external IO) using Testcontainers-style thinking, with a fixture strategy and CI-friendly execution. Use when IO/DB bugs, wiring issues, or production-only behavior must be reproduced.

Installation

$ npx skills add smithery/hzeroxium --skill java-testing-integration

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery/hzeroxium.

npx skills add smithery/hzeroxium

Browse all from smithery/hzeroxium

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Skill metadata

Parsed from SKILL.md frontmatter.

Version0.1.0
LicenseCC-BY-4.0
Compatibility17+ (recommended 21), Maven or Gradle, JUnit 5 (preferred)
More metadata
owner
backend-platform
version
0.1.0
tags
["java","testing","integration","testcontainers","ci"]

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 8,837 B
  • docs SUMMARY.md 279 B

History

  1. First recorded snapshot · 0 installs

SKILL.md

Java Integration Testing (Reproducible, CI-Friendly)

Why this skill exists

Integration tests catch failures that unit tests cannot: incorrect wiring, serialization/deserialization, transaction boundaries, connection pool settings, schema drift, message ack/retry behavior, and “works on my machine” config issues.

The goal is NOT to replace unit tests. The goal is to:

  • Reproduce IO/DB/queue bugs deterministically
  • Validate runtime wiring (config, DI, modules, migrations)
  • Provide confidence that changes remain deployable

Scope

In scope

  • Integration tests for:

- SQL/NoSQL DB interactions (schema + queries + transactions) - Message broker interactions (publish/consume at a boundary level) - HTTP client integration with a fake/stub server (WireMock-like thinking) - Persistence + serialization + config binding behavior

  • Testcontainers-style isolation, ephemeral infra, reproducible setup/teardown
  • Fixture strategy (data builders, seed scripts, migrations, reset strategy)
  • CI performance and flake-proofing

Out of scope

  • Full end-to-end testing across multiple real services in a shared environment
  • Load/performance testing (see java-load-testing)
  • Security penetration or exploit workflows (see java-security-audit for defensive review)

When to use (Triggers)

  • “It fails only in staging/prod”
  • “Works locally but fails in CI”
  • Bugs involving:

- transactions / isolation levels / deadlocks - schema migrations / SQL differences - connection pooling / timeouts - message redelivery / ordering / duplicates

  • You need a regression test for a production incident that involved IO.

Required inputs (Context to request/collect)

  • Build tool: Maven/Gradle
  • Test framework: JUnit 5 (preferred)
  • Runtime stack hints:

- DB type + version (Postgres/MySQL/Mongo/etc.) - Broker type + version (Kafka/RabbitMQ/etc.)

  • App config entry points:

- how config is loaded (env vars, properties, yaml) - how DB/broker urls are injected

  • CI constraints:

- max test time budget - whether Docker is available in CI runners

Core principles (Non-negotiables)

  1. Determinism over realism

- “Real enough to catch the bug” is the target, not “simulate production perfectly”.

  1. Isolation by default

- No shared dev DB, no shared staging topics, no reliance on external services.

  1. Minimize flakiness

- Avoid timing sleeps; use waits, health checks, and bounded timeouts.

  1. Keep it fast

- Integration tests should be fewer than unit tests and run in reasonable time.

Test design: the 3-layer model

Layer A: Pure unit tests

  • No IO. Fast. Most coverage lives here.

Layer B: “Narrow integration tests”

  • One integration boundary at a time:

- repository ↔ DB - publisher ↔ broker - client ↔ stub server

  • This is your default integration layer.

Layer C: “Slice tests” / module wiring tests

  • Validate module wiring and config, but still isolate external dependencies via containers/stubs.

Container strategy (Testcontainers-style)

Container lifetime

Prefer “one container per test class / per suite”:

  • Start container once, reuse across test methods
  • Reset data between tests (truncate tables / recreate schema / transactional rollback)
  • This is typically faster than per-test containers

Networking & reachability

  • Containers should be reachable from tests running on host.
  • When multi-container scenarios are needed, use a shared network and stable aliases.

Version pinning

  • Pin container images (avoid “latest”).
  • Document why a version is chosen and how to upgrade safely.

Fixture strategy (Make tests readable and maintainable)

Pick ONE of the following and be consistent:

Option 1: Migration-first + seed scripts

  • Run schema migrations on startup (preferred)
  • Seed minimal reference data via SQL scripts or migration “baseline data”
  • For each test: insert test-specific rows + cleanup

Option 2: Programmatic builders

  • Use “Test Data Builders” (factory methods) to create domain objects
  • Persist through repositories (closer to real app behavior)
  • Cleanup through explicit teardown or truncation

Option 3: Snapshot fixtures (use sparingly)

  • Predefined dataset snapshots loaded into DB
  • Risk: harder to evolve, can become brittle

Reset strategy (Pick a reset mechanism)

  • If DB supports transactions and app boundaries allow:

- wrap each test in a transaction and roll back

  • Otherwise:

- truncate relevant tables between tests (fast for relational) - or recreate schema for each class (slower but simpler)

Implementation checklist (Step-by-step)

  1. Create test source layout

- src/test/java/... - src/test/resources/... (sql seeds, config overrides)

  1. Add dependencies

- JUnit 5 - Testcontainers core + module for your DB/broker

  1. Implement container bootstrap

- Prefer static container per class - Expose connection info to the app under test (env vars / system props / config injection)

  1. Implement health + readiness checks

- Avoid arbitrary sleeps - Use bounded waits and timeouts

  1. Write the test with AAA structure

- Arrange: set fixtures - Act: call the boundary - Assert: verify state (DB rows, messages, outputs)

  1. Add failure diagnostics

- On failure, log: - container logs (bounded) - effective config (redact secrets) - SQL statements if relevant (optional)

  1. Make it CI-friendly

- Ensure tests run headless - Keep timeouts appropriate - Ensure Docker availability in CI or provide a fallback profile

Example: JUnit 5 + Postgres container (framework-agnostic pseudo-code)

@Testcontainers
class UserRepositoryIT {

  @Container
  static PostgreSQLContainer<?> postgres =
      new PostgreSQLContainer<>("postgres:16.2")
          .withDatabaseName("testdb")
          .withUsername("test")
          .withPassword("test");

  @BeforeAll
  static void init() {
    System.setProperty("DB_URL", postgres.getJdbcUrl());
    System.setProperty("DB_USER", postgres.getUsername());
    System.setProperty("DB_PASS", postgres.getPassword());
    // Run migrations here if your framework doesn't auto-run them.
  }

  @BeforeEach
  void reset() {
    // truncate tables or reset fixtures
  }

  @Test
  void savesAndLoadsUser() {
    // Arrange
    var user = new User("u1", "[email protected]");
    // Act
    repo.save(user);
    var loaded = repo.findById("u1");
    // Assert
    assertThat(loaded).isPresent();
    assertThat(loaded.get().email()).isEqualTo("[email protected]");
  }
}

Definition of Done (DoD)

  • [] Test is deterministic (no sleeps; bounded waits)
  • [] Test can run on a clean machine with only Docker + JDK
  • [] Test cleans up after itself (no state leakage)
  • [] Test runtime is within budget (document budget)
  • [] Failure output includes enough diagnostics to debug
  • []Added regression coverage for the original incident/bug

Guardrails (What NOT to do)

  • Never depend on:

- shared dev databases

- real staging brokers

- external internet services

  • Never commit secrets into test configs
  • Avoid:

- random ports without discovery

- time-based sleeps for readiness

- “mega integration test” covering 10 subsystems in one test

Common failure modes & fixes

  • Flaky startup → readiness checks missing → add health wait + extend startup timeout
  • CI fails, local passes → Docker not available / resources limited → adjust CI runner or mark tests as “requires docker”
  • Slow tests → per-test container startup → switch to per-class containers + truncation reset
  • Data collisions → shared fixtures → generate unique ids + isolate test data

Outputs / Artifacts

  • src/test/java/**/...IT.java integration tests
  • src/test/resources/ seed scripts or fixture configs
  • CI job updates:

- ensure docker enabled

- split unit vs integration stage if needed

Optional:

  • docs/testing/integration-testing.md runbook

References (official docs)