This walkthrough gets a minimal @HopPipeline test running against H2, then shows how to run the same test against a real Oracle container.

1. Add the dependencies

Declare the modules that give you the Hop fixture and the H2 database backend:

<dependencies>
  <dependency>
    <groupId>io.yupiik.hop.junit</groupId>
    <artifactId>hop-junit-core</artifactId>
    <version>1.0.0-SNAPSHOT</version>
  </dependency>
  <dependency>
    <groupId>io.yupiik.hop.junit</groupId>
    <artifactId>hop-junit-database-api</artifactId>
    <version>1.0.0-SNAPSHOT</version>
  </dependency>
  <dependency>
    <groupId>io.yupiik.hop.junit</groupId>
    <artifactId>hop-junit-database-core</artifactId>
    <version>1.0.0-SNAPSHOT</version>
  </dependency>
  <dependency>
    <groupId>io.yupiik.hop.junit</groupId>
    <artifactId>hop-junit-database-h2</artifactId>
    <version>1.0.0-SNAPSHOT</version>
  </dependency>
</dependencies>

The backend is selected from the database.default.implementation system property, which defaults to H2. Nothing else is needed.

Add the org.apache.hop:hop-transform-* and org.apache.hop:hop-action-* artifacts for the transforms and actions your pipeline or workflow actually uses (versions managed by the hop-junit parent POM); hop-junit-core does not bundle any plugin jar. If your dataset is an .xls/.xlsx workbook, also add org.apache.poi:poi and org.apache.poi:poi-ooxml.

2. Prepare a minimal pipeline

Put a tiny pipeline under src/test/resources/repositories/ (or any folder you point at via projectHome). For example hello.hpl that sets a result field or just starts and finishes.

3. Write the test

package com.acme;

import static org.junit.jupiter.api.Assertions.assertEquals;

import io.yupiik.hop.junit.database.DbExpected;
import io.yupiik.hop.junit.database.DbInit;
import io.yupiik.hop.junit.database.JdbcConnectionSpec;
import io.yupiik.hop.junit.database.JdbcNamed;
import io.yupiik.hop.junit.hop.HopPipeline;
import io.yupiik.hop.junit.hop.HopPipelineFixture;
import org.junit.jupiter.api.Test;

class HelloTest {

    @Test
    @HopPipeline(value = "repositories/hello.hpl",
            projectHome = "src/test/resources",
            runConfiguration = "local")
    void runs(final HopPipelineFixture pipeline) {
        pipeline.with("greeting", "hello")
                .execute()
                .assertSuccess();
    }
}

The HopPipelineFixture wires the Hop project home, resolves the .hpl, configures the local run configuration, sets the parameters, and returns a fluent HopPipelineExecution you can assert on.

4. Seed and verify a named database

The @Database facade and its @DbInit / @DbExpected contract are the idiomatic way to seed a database and assert its post-conditions. Put an SQL schema script and a dataset on the test classpath, then:

@Test
@Database(name = "SRC", init = {
        @DbInit("ddl/schema.sql"),
        @DbInit(value = "datasets/prep.yml", operation = DatasetOperation.CLEAN_INSERT),
}, expected = @DbExpected("datasets/expected.yml"))
void seededDatabaseCanBeInjected(@JdbcNamed("SRC") final JdbcConnectionSpec src) {
    // src.jdbcUrl() is the plain H2 URL; databaseTypeName() is "H2" (or "ORACLE").
    assertEquals("H2", src.databaseTypeName());
}

@Database is backend-agnostic: the H2 backend provides an Oracle-compatible H2 database (H2DatabaseMode.ORACLE_EXTENDED by default) with a SQL rewrite driver, so Oracle-style SQL and dictionary paths run unchanged. Use @H2Database when you need H2-specific knobs (e.g. a different mode).

5. Run

mvn test

The H2 backend is fully in-memory - no Docker, no external service.

Running the same tests against real Oracle

To exercise the identical test body against a real Oracle 23ai Free container, add the Oracle module inside your own -Poracle Maven profile (the Oracle module itself declares its dependencies unconditionally; the profile is the switch that decides when they are present):

<profiles>
  <profile>
    <id>oracle</id>
    <properties>
      <database.default.implementation>ORACLE</database.default.implementation>
      <oracle.image>gvenzl/oracle-free:23-slim-faststart@sha256:f5ff19033860d662c821cb04eb10483fa94f14f78eae252d054291ea07028093</oracle.image>
    </properties>
    <dependencies>
      <dependency>
        <groupId>io.yupiik.hop.junit</groupId>
        <artifactId>hop-junit-database-oracle</artifactId>
        <version>1.0.0-SNAPSHOT</version>
      </dependency>
    </dependencies>
    <build>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-surefire-plugin</artifactId>
          <configuration>
            <systemPropertyVariables>
              <database.default.implementation>ORACLE</database.default.implementation>
              <oracle.image>${oracle.image}</oracle.image>
            </systemPropertyVariables>
          </configuration>
        </plugin>
      </plugins>
    </build>
  </profile>
</profiles>

Then run with Docker:

mvn verify -Poracle

What changes behind the scenes:

  • the @Database facade now resolves the ORACLE backend via ServiceLoader;

  • each named database becomes a schema (SRC, TGT, ...) on a single shared Oracle container;

  • the per-test lifecycle drops and recreates the schema so every test starts isolated (mirroring H2's fresh-per-test in-memory database);

  • your tests and datasets are unchanged - which is the whole point of the facade.

If the selected backend module is missing from the classpath, DatabaseExtension fails fast with a message telling you to add hop-junit-database-h2 or hop-junit-database-oracle.