3.9 KiB
EDU-016 — Move PostgreSQL-specific Education persistence tests off H2
- Status: done — focused PostgreSQL persistence suite passes against the reachable
postgresdbseam - Type: test infrastructure / PostgreSQL integration
- Phase: 0 / database prerequisite
- Blockers: EDU-002, EDU-005 for final schema ownership
Confirmed defect
Education unit tests use H2 with MODE=MYSQL, while production Mapper SQL intentionally uses PostgreSQL ON CONFLICT. H2 rejects the annotated SQL for favorites, wrong-question idempotency, unified answer/submit idempotency, and review-session conflict handling. Switching H2 to PostgreSQL mode does not solve this: H2 still rejects ON CONFLICT and also exposes Boolean/integer compatibility differences.
This prevents the full Practice/Wrong/Favorite regression suite from exercising production persistence semantics.
Outcome
PostgreSQL-specific persistence behavior runs against real ephemeral PostgreSQL in the test suite, while fast database-independent tests may remain on H2 where their SQL is portable.
Scope
- Select the repository-standard PostgreSQL integration-test mechanism, preferably Testcontainers or an existing project fixture.
- Move tests that execute
ON CONFLICT, PostgreSQL JSON/JSONB, identity, Boolean, or concurrency semantics onto PostgreSQL. - Keep controller and pure domain tests database-independent.
- Align test schema with module-owned Flyway after EDU-005/EDU-006; avoid maintaining a divergent hand-written full schema long term.
- Cover at least:
IdempotencyStoreMapper.insertIgnore;- wrong-question idempotency insert;
- favorite upsert;
- review-session insert-ignore;
- concurrent answer and submit claims.
Acceptance criteria
- No test relies on H2 to validate PostgreSQL
ON CONFLICTsemantics. - PostgreSQL tests execute the same Mapper SQL as production.
- Test database is isolated and disposable.
- Schema setup uses Flyway or an explicitly temporary bridge with an exit ticket.
- Concurrency tests are stable and prove unique-constraint behavior.
- CI prerequisites and local commands are documented.
Verification
Completed against the existing reachable postgresdb service with credentials supplied only through EDU_TEST_POSTGRES_* environment variables:
mvn -pl yudao-module-education \
-Dtest=PracticeSessionMapperTest,FavoriteServiceImplTest,PracticeAnswerServiceImplTest,PracticeSubmitServiceImplTest,PracticeSubmitProjectionIntegrationTest,WrongQuestionServiceImplTest test
Result: 140 tests passed, 0 failures, 0 errors. The same 140-test suite also passed with JUnit class parallelism explicitly enabled, proving the shared schema resource lock prevents class-level collisions. The suite executes production Mapper SQL on PostgreSQL, including ON CONFLICT and JSONB behavior. A JUnit resource lock serializes PostgreSQL test classes that share one random JVM-scoped schema; each class closes its Spring context before the inherited lifecycle drops and recreates that schema, preventing cached contexts from reusing a dropped schema.
The temporary schema bridge was removed by EDU-006. PostgreSQL persistence tests now create their disposable random schema through the module-owned Flyway chain (V4010, V4020, V4030) and retain only clean.sql for per-test data isolation.
Local/CI prerequisites:
- a reachable disposable PostgreSQL database;
- PostgreSQL JDBC connectivity from the Maven process;
- non-blank
EDU_TEST_POSTGRES_HOST,EDU_TEST_POSTGRES_PORT,EDU_TEST_POSTGRES_DB,EDU_TEST_POSTGRES_USER, andEDU_TEST_POSTGRES_PASSWORDvalues.
No Testcontainers or other external dependency was added. No PostgreSQL Flyway migration was executed or authorized by this ticket.
Risk and rollback
- Risk: Medium CI/runtime cost; high value for persistence confidence.
- Rollback: Keep prior fast tests temporarily, but do not restore false H2 coverage claims for PostgreSQL SQL.