Compile-Time Safety
Declare tables and columns as standard Java interfaces. Catch typos and schema breakages during compilation.
Type-safe, zero-boilerplate database test fixtures for modern Java.
Setting up and verifying relational database fixtures in Java tests has traditionally been painful and fragile. JDBScript bridges this gap:
While DbUnit established dataset-driven testing in Java, maintaining external XML/YAML datasets imposes recurring maintenance overhead as applications evolve.
| Dimension | DbUnit Datasets | JDBScript |
|---|---|---|
| Schema Drift | Silent failures at test runtime | Immediate compile errors in the IDE |
| Refactoring | Fragile text search across external files | Automated IDE rename and reference updates |
| Fixture Boilerplate | Must specify all non-null columns per row | Smart defaults generate IDs and non-essential columns |
| Type Safety | Stringly-typed data; manual converters for Enums/UUIDs | Native Java types, Enums, and automatic JDBC conversion |
| Sequence Management | Manual sequence reset scripts to avoid ID collisions | Automatic sequence restarts preventing ID collisions |
Add the jdbscript dependency to your project's test scope:
<dependency>
<groupId>org.jdbscript</groupId>
<artifactId>jdbscript</artifactId>
<version>1.3.0</version>
<scope>test</scope>
</dependency>testImplementation("org.jdbscript:jdbscript:1.3.0")testImplementation 'org.jdbscript:jdbscript:1.3.0'Define lightweight interfaces extending IDBSchema and IDBRecord to reflect your tables and columns:
import org.jdbscript.IDBSchema;
import org.jdbscript.IDBSchema.IDBRecord;
public interface IAppSchema extends IDBSchema {
IUserRecord users();
IOrderRecord orders();
interface IUserRecord extends IDBRecord {
IUserRecord id(Long id);
IUserRecord username(String username);
IUserRecord email(String email);
IUserRecord active(Boolean active);
}
interface IOrderRecord extends IDBRecord {
IOrderRecord id(Long id);
IOrderRecord user_id(Long userId);
IOrderRecord total_amount(Double amount);
}
}resetDB Initialize JDBEngine and wipe tables & insert fixtures in a single fluent call:
import org.jdbscript.JDBEngine;
import org.jdbscript.IJDBEngine;
import javax.sql.DataSource;
DataSource dataSource = getDataSource();
IJDBEngine<IAppSchema> engine = JDBEngine.builder(IAppSchema.class)
.dataSource(dataSource)
.build();
// Wipes schema tables and inserts records in FK-safe order
engine.resetDB(db -> {
db.users().id(1L).username("alice").email("[email protected]").active(true);
db.users().id(2L).username("bob").email("[email protected]").active(false);
db.orders().id(1001L).user_id(1L).total_amount(59.99);
});assertDB Assert that expected records exist or do not exist using the same intuitive syntax:
// Assert that records exist in the database
engine.assertDBHas(db -> {
db.users().username("alice").active(true);
db.orders().user_id(1L).total_amount(59.99);
});
// Assert that records do not exist
engine.assertDBHasNot(db -> {
db.users().username("charlie");
});Runnable, self-contained example projects demonstrating real-world usage patterns across different stacks:
01-quickstart) — Standard JUnit 5 Arrange-Act-Assert lifecycle with type-safe schema fixtures.03-recordtools-defaults) — Avoid dummy fixture boilerplate by populating only the columns relevant to your test while smart defaults automatically populate non-essential NOT NULL columns.02-class-scripts-and-include) — Avoid copy-pasting shared test data by composing modular baseline scripts, and perform type-safe state transitions mid-test.04-scripting-power) — Generate large-scale test datasets in a few lines of Java code without bloated fixture files or flaky, non-deterministic random data.06-insert-power) — Append new records mid-test with insertDB to simulate incoming events and state progressions without wiping existing data.09-liquibase-data-migration) — Verify column backfills and transformations by seeding pre-migration shape and asserting post-migration state.10-flyway-data-migration) — Test Flyway version migrations step-by-step with intermediate state assertions.11-domain-dsl-and-helpers) — Seed complex multi-table business entities cleanly by extending schemas with domain helper methods via engine.as(...).05-custom-converters) — Mapping domain value objects (e.g., Money) to JDBC columns via IJDBTypeConverter.08-springboot) — Seed and reset database state in @SpringBootTest integration tests via auto-configured DataSource.07-testcontainers) — Manage fixture state and test data seamlessly in Testcontainers (e.g. PostgreSQL) via standard DataSource integration.12-kotlin-dsl) — Write concise, type-safe database schemas and test fixtures in Kotlin test suites.