Testing Utilities

GitLab Docs Pipeline Coverage License
A collection of testing utilities for Java projects, providing fake concurrency primitives (clocks, executors), console I/O capture, classpath resource helpers, Kubernetes ConfigMap simulation, and random text generation. Includes dedicated integration modules for both JUnit 4 and JUnit 5 with annotation-driven configuration and parameter injection.

See morimekta.net/utils for procedures on releases.

Getting Started

To add to maven: Add this line to pom.xml under dependencies:

<dependencies>
    <dependency>
        <groupId>net.morimekta.utils</groupId>
        <artifactId>testing</artifactId>
        <version>5.6.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>net.morimekta.utils</groupId>
        <artifactId>testing-junit4</artifactId>
        <version>5.6.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>net.morimekta.utils</groupId>
        <artifactId>testing-junit5</artifactId>
        <version>5.6.1</version>
        <scope>test</scope>
    </dependency>
</dependencies>

To add to gradle: Add this line to the dependencies group in build.gradle:

testImplementation 'net.morimekta.utils:testing:5.6.1'
testImplementation 'net.morimekta.utils:testing-junit4:5.6.1'
testImplementation 'net.morimekta.utils:testing-junit5:5.6.1'

Testing

General testing utilities.

Concurrency Utils

  • FakeClock: A fake implementation of java.time.Clock that holds time constant until explicitly advanced via tick(). Listeners can be registered to be notified when time progresses, making it easy to test time-dependent code deterministically without real delays.

java FakeClock clock = FakeClock.forCurrentTimeMillis(1234567890_000L); clock.addListener(newInstant -> System.out.println("Time: " + newInstant)); clock.tick(Duration.ofSeconds(5));

  • FakeScheduledExecutor: A ScheduledExecutorService that uses a FakeClock as its time source and executes tasks in a real background thread pool. Tasks are triggered when the fake clock is ticked, giving you control over when scheduled work runs while still exercising real concurrency.

```java FakeClock clock = new FakeClock(); FakeScheduledExecutor executor = new FakeScheduledExecutor(clock);

Future future = executor.schedule(() -> "done", 100, MILLISECONDS); assertThat(future.isDone(), is(false));

clock.tick(100); Thread.sleep(10); // let background thread complete assertThat(future.get(), is("done")); executor.shutdown(); ```

  • ImmediateExecutor: An ExecutorService that runs all submitted tasks synchronously in the calling thread. The task completes before submit() returns, so the returned future is always already done. Useful for removing threading complexity from unit tests.

java ImmediateExecutor executor = new ImmediateExecutor(); Future<String> future = executor.submit(() -> "immediate"); assertThat(future.isDone(), is(true)); assertThat(future.get(), is("immediate"));

  • ImmediateScheduledExecutor: A ScheduledExecutorService that uses a FakeClock for scheduling and runs tasks synchronously in the thread that triggers the clock tick. Unlike FakeScheduledExecutor, no background threads are involved, making tests fully deterministic and single-threaded.

```java FakeClock clock = new FakeClock(); ImmediateScheduledExecutor executor = new ImmediateScheduledExecutor(clock);

AtomicInteger counter = new AtomicInteger(0); executor.scheduleAtFixedRate(counter::incrementAndGet, 0, 100, MILLISECONDS);

clock.tick(100); assertThat(counter.get(), is(1)); clock.tick(200); assertThat(counter.get(), is(3)); ```

Console Utils

  • Console: An interface for controlling and inspecting console I/O during testing. Provides access to a fake TTY and captured stdout/stderr content, and allows setting stdin programmatically.

java console.setInput("yes\n"); System.out.println("Hello"); assertThat(console.output(), is("Hello\n"));

  • ConsoleManager: Base class that hijacks System.in, System.out, and System.err with fake implementations for the duration of a test. Captured output can be inspected via the Console interface, and the original streams are restored after each test. Supports dumping captured output on test failure for easier debugging.

I/O and File Utils

  • ResourceUtil: Utility class for loading classpath resources in tests. Can copy a resource to a filesystem path or read its content as a string, using the calling class as the resource loading context.

java Path file = ResourceUtil.copyResourceTo("/schema.sql", tempDir); String content = ResourceUtil.resourceAsString("/test-data.json");

  • TestConfigMap: Wraps a directory to simulate a Kubernetes ConfigMap volume mount for testing. Manages versioned snapshots with symbolic links and supports atomic updates via a try-with-resources transaction, just like a real ConfigMap mount.

java TestConfigMap config = new TestConfigMap(tempDir); try (var update = config.update()) { update.copyResource("/default-config.txt"); update.writeContent("custom.txt", "value"); } assertThat(config.getPath("custom.txt"), exists());

Text Utils

  • EnglishWords: A lightweight random text generator for producing dummy test data. Generates random English words, sentences, paragraphs, and standard Lorem Ipsum text using a simple subject-verb-object sentence pattern.

java String word = EnglishWords.word(); // e.g. "dog" String sentence = EnglishWords.sentence(50); // at least 50 chars String para = EnglishWords.paragraph(3); // 3 sentences String lorem = EnglishWords.loremIpsum();

JUnit 4

Utilities specialized for JUnit 4.

  • ConsoleWatcher: A JUnit 4 TestWatcher @Rule that sets up a fake console before each test and restores the original system streams afterward. Provides fluent configuration for terminal size, interactivity, and dumping output on test failure.

```java @Rule public ConsoleWatcher console = new ConsoleWatcher() .withTerminalSize(20, 80) .interactive() .dumpOnFailure();

@Test public void testOutput() { System.out.println("Hello"); assertThat(console.console().output(), containsString("Hello")); } ```

  • DataProviderUtil: Utility for com.tngtech.java:junit-dataprovider that generates the Cartesian product of multiple parameter dimensions. Pass in lists of values for each dimension and get back a 2D array of all combinations, simplifying parameterized test setup.

java @DataProvider public static Object[][] testParams() { return DataProviderUtil.buildDataDimensions( List.of(ContentType.WALLPAPER, ContentType.AUDIO), List.of(Locale.US, Locale.DE) ); // Produces: [WALLPAPER,US], [WALLPAPER,DE], [AUDIO,US], [AUDIO,DE] }

JUnit 5

Utilities specialized for JUnit 5.

  • ConsoleExtension: A JUnit 5 extension that provides fake console I/O with parameter injection support. Injects Console or TTY directly into test method parameters, and supports annotations like @ConsoleSize, @ConsoleInteractive, and @ConsoleDumpOutputOnFailure for configuration.

java @ExtendWith(ConsoleExtension.class) @ConsoleSize(rows = 20, cols = 80) @ConsoleInteractive public class MyTest { @Test public void testOutput(Console console) { System.out.println("Hello"); assertThat(console.output(), containsString("Hello")); } }

  • ParamsProviderUtil: Utility for JUnit 5 @ParameterizedTest with @MethodSource that generates the Cartesian product of parameter dimensions. Transforms multiple Arguments objects into a Stream<Arguments> of all combinations.

```java public static Stream params() { return ParamsProviderUtil.buildArgumentDimensions( arguments(ContentType.WALLPAPER, ContentType.AUDIO), arguments(Locale.US, Locale.DE) ); }

@ParameterizedTest @MethodSource("params") public void test(ContentType type, Locale locale) { ... } ```

  • DataSourceExtension: A JUnit 5 extension that manages a JDBC DataSource for database testing. Creates an in-memory H2 database by default and supports parameter injection of Jdbi, DataSource, or the connection URI string. Use annotations like @DataSourceMode, @DataSourceSchema, and @DataSourceDriverClass to configure the database engine and initial schema.

java @ExtendWith(DataSourceExtension.class) @DataSourceMode(DataSourceMode.Mode.POSTGRESQL) public class MyDatabaseTest { @Test @DataSourceSchema("/schema.sql") public void testQuery(Jdbi jdbi) { var db = jdbi.onDemand(MyDBI.class); assertThat(db.queryUsers(), is(notNullValue())); } }

Major Version Changes

  • 4.x -> 5.x: FakeScheduledExecutor renamed ImmediateScheduledExecutor and new FakeScheduledExecutor created using a real background executor, but using the fake clock to trigger the scheduled tasks.