Modules
Hop JUnit is split into a parent aggregator and small, focused modules. You only pull in what your tests actually need.
Database modules
The database testing framework is grouped under the hop-junit-database-parent aggregator:
-
hop-junit-database-api- the engine-agnostic contract. It definesBaseDatabaseExtension(the backend SPI), theDescriptor/ManagedDatabaserecords, and the pure-JDK types@DbInit,@DbExpected, theDbComparison,DatasetFormat,DatasetOperation,DatabaseImplementation,JdbcNamedandJdbcConnectionSpec. It has no DBUnit and no Apache Hop dependency. -
hop-junit-database-core- the@Databasefacade (and its repeatable container@Databases) and itsDatabaseExtension. It resolves the backend throughjava.util.ServiceLoader(DatabaseExtensionRegistry), matchingBaseDatabaseExtension.name()againstDatabaseImplementation.current(). No backend type is referenced here, so the backend jars may be absent until the facade actually needs them. -
hop-junit-database-testcontainers- the sharedTestContainerDatabaseExtensionbase used by the container-backed backends (H2 has its own in-memory path, Oracle and Testcontainers derive from this). It depends only on the API module. -
hop-junit-database-dataset- the DBUnit dataset engine (DbUnitEngine), the SQL script runner (SqlScriptRunner) and the resource resolver (DatasetResourceResolver). Both H2 and Oracle seed and verify throughDbUnitEngine, so this module sits on top of the testcontainers base. It supports the YAML, XML, CSV and JSON dataset formats out of the box; XLS/XLSX (XlsDataSet) needs Apache POI on the test classpath and is documented in the API page. -
hop-junit-database-h2- the H2 backend (H2DatabaseExtension,@H2Databaseand its repeatable container@H2Databases), an in-memory Oracle-compatible H2 database, theH2DatabaseModeenum, and a JDBC driver (H2SqlRewriteDriver) that rewrites Oracle SQL for H2. Registered for theH2implementation.
|
NOTE
|
To extend the built-in Oracle-to-H2 rewrites without changing this module, subclass |
|
NOTE
|
Oracle compatibility is partial: H2 tables are not physically partitioned and the rewrite removes
PARTITION(...) on reads, so reads include the whole fixture table, not just the named partition. Partition-targeted writes are rejected instead of silently broadening their effect. Ordered XMLCAST(XMLAGG(XMLELEMENT(name, scalar_text) ORDER BY ...) AS CLOB) is supported for one scalar text argument, preserving surrounding RTRIM expressions, XML characters, nulls and large character results; it is not a general XML engine. The H2 _ROWID_ and ORA_HASH shim support repeatable reader bands for unchanged fixture rows but do not reproduce Oracle row identifiers or hash values. Whole-query application templates are not emulated by this driver. Single-named-source CONNECT BY queries with LEVEL termination are lowered to recursive CTEs, including qualified PRIOR columns, START WITH, post-hierarchy filters and duplicate source rows. This subset does not implement Oracle cycle detection, NOCYCLE, hierarchy path functions, sibling ordering, joined/derived sources, or binds inside the hierarchy block; unsupported shapes must not be treated as Oracle-equivalent. A missing or zero upper bound still emits the root, as on Oracle. Date arithmetic translation recognizes explicit Oracle date expressions and TO_DATE projection aliases, not arbitrary JDBC column types; date differences use numeric days at Oracle DATE second precision. Date-plus/minus-numeric CASE operands support searched, simple and nested cases when every result branch is a numeric literal, bind, TO_NUMBER, numeric cast, arithmetic over those forms, or NULL (including an omitted ELSE). Conditions and selectors are preserved, fractional offsets retain time-of-day, and unknown column/function result types or mixed date/text branches are left untranslated rather than assumed numeric. Date aliases are inferred from their own CTE projections, not unrelated projections sharing the same column name; this is conservative inference, not general SQL type resolution. DBMS_XMLGEN.GETXML executes a single SELECT on the active connection, serializes ROWSET/ROW XML, omits null columns, and returns null for no rows. It excludes writes, multiple statements and WITH queries, but does not sandbox user-installed SQL functions. XMLTABLE/PASSING, namespaces, arbitrary XML column names and complete Oracle XML serialization parity remain unsupported. In ORACLE_EXTENDED mode the ALL_TABLES, ALL_TAB_COLS, ALL_TAB_COLUMNS and ALL_CONSTRAINTS dictionaries are auto-installed as H2 views over INFORMATION_SCHEMA, so they always reflect the real schema (including SA.X FOR PUBLIC.X synonyms reported under the SA owner). The partition/app-metadata dictionaries (ALL_TAB_PARTITIONS, ALL_PART_TABLES, ALL_PART_KEY_COLUMNS, ALL_PART_INDEXES, ALL_IND_PARTITIONS and the USER_* index views) are installed as empty Oracle-typed scaffold tables that the consumer seeds with its own partition data; neither dictionary type should be re-created by the consumer. Schema-qualified references must be backed by real H2 schemas or synonyms; no schema prefix is silently removed. SHA-1 character input is encoded as UTF-8 for H2, which matches Oracle only when the Oracle database uses a compatible character encoding.
|
Hop execution and coverage
-
hop-junit-core- the Hop testing engine and scope coverage: -
@HopPipeline/@HopPipelineFixture/@HopPipelineExtensionto run pipelines, -
@HopWorkflow/@HopWorkflowFixture/@HopWorkflowExtensionto run workflows, -
@HopParameters/@HopParameterfor execution parameters, -
HopExecutionAssertionsand the fluentassertSuccess()/assertFailure()/assertLogContains()API, -
the coverage package under
io.yupiik.hop.junit.hop.coverage:HopCoverageRuntime, the collectors, the post-processor, and the generic renderers. It also registers aLauncherSessionListenerso coverage is aggregated and reported when the test session closes.
hop-junit-core intentionally depends only on hop-core and hop-engine, not on concrete transform/action plugin jars. Pipelines and workflows are deserialized at runtime, so you must add the hop-transform-* and hop-action-* artifacts that your .hpl/.hwf files actually use to your own test dependencies, for example org.apache.hop:hop-transform-tableinput or org.apache.hop:hop-action-sql. Their versions are managed by the hop-junit parent POM.
To keep the shipped classpath lean, hop-junit-core also excludes the heavy optional subsystems that hop-core/hop-engine transitively pull in: the entire Jetty web/REST/SOAP server stack (Jetty, Jersey, Metro, Jakarta WS/SOAP/WS APIs, including jetty-util), the Maven-resolver plugin-download layer, the CommonMark renderer, the gRPC remote-execution stack, Avro serialization (+ its Jackson dataformat), the Batik SVG renderer, the Rhino JavaScript engine, Snappy compression, the picocli CLI, the WebDAV VFS provider (commons-vfs2-jackrabbit2), JWT (nimbus-jose-jwt) and the legacy Apache HttpClient 4.x httpcore. Those are lazily loaded by Hop and never touched by the local pipeline engine that hop-junit-core exercises, so the local runtime is unaffected. The servlet API, io.smallrye:jandex and the Apache HttpClient 5 stack (httpclient5/httpcore5/httpcore5-h2) are deliberately retained because the Hop environment, plugin registry and VFS require them during bootstrap (jakarta.servlet.http.HttpServlet, org.jboss.jandex.IndexView in PluginRegistry, org.apache.hc.core5.ssl.TrustStrategy in HopVfs). The MinimalClasspathSafetyNetTest guards this: it boots the environment and fails if a trimmed stack is accidentally re-introduced or a retained class stops linking. A consumer who needs Hop's embedded web server, gRPC server, SVG rendering or WebDAV must add those artifacts explicitly.
-
hop-junit-documentation- this site.
Which modules do I need?
| Use case | Modules |
|---|---|
|
Run a pipeline or workflow test with H2 |
|
|
Same tests against real Oracle (add your own |
the H2 set + |
|
Only the |
|
Oracle module placement
hop-junit-database-oracle declares its Oracle dependencies (Testcontainers oracle-free, ojdbc11, hop-databases-oracle) unconditionally. It is you, the downstream consumer, who decides when those are present: put the hop-junit-database-oracle dependency inside your own -Poracle Maven profile and set database.default.implementation=ORACLE in that profile. Without the profile, only the pure H2 modules are on the classpath and H2 remains the default.
See the Quickstart
for a concrete -Poracle profile.