-
Notifications
You must be signed in to change notification settings - Fork 21
developer testing guide
This guide explains how to run and write tests for Morphium. It covers the test infrastructure, the MultiDriverTestBase class, and the runtests.sh script.
# Fast local testing with InMemoryDriver (no MongoDB needed)
./runtests.sh --driver inmem --restart
# Test against PoppyDB (single node - recommended for most testing)
./runtests.sh --poppydb --driver pooled --restart
# Test against PoppyDB replica set (for replication testing)
./runtests.sh --poppydb-replicaset --driver pooled --restart
# Run specific test class
./runtests.sh --driver inmem --test BasicFunctionalityTest
# Run with Maven directly
mvn test -Dmorphium.test.driver=inmem -Dtest=BasicFunctionalityTest┌─────────────────────────────────────────────────────────────────┐
│ runtests.sh │
│ (orchestrates test runs, manages PoppyDB, collects stats) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Maven Surefire Plugin │
│ (executes JUnit 5 tests with system properties) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ MultiDriverTestBase │
│ (provides Morphium instances configured per driver type) │
└─────────────────────────────────────────────────────────────────┘
│
┌───────────────┼───────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────────┐
│InMemory │ │ Pooled │ │SingleConnect │
│ Driver │ │ Driver │ │ Driver │
└──────────┘ └──────────┘ └──────────────┘
│ │ │
▼ ▼ ▼
┌──────────┐ ┌─────────────────────────────┐
│In-Memory │ │ MongoDB / PoppyDB │
│ Storage │ │ │
└──────────┘ └─────────────────────────────┘
MultiDriverTestBase is the foundation for parameterized tests that run against multiple driver types.
-
Test classes extend
MultiDriverTestBaseand use JUnit 5@ParameterizedTestwith@MethodSource -
Method sources like
getMorphiumInstances()returnStream<Arguments>with pre-configuredMorphiuminstances -
Each test method receives a
Morphiuminstance as parameter and runs independently -
Database isolation: Each driver instance gets a unique database name (
morphium_test_1,morphium_test_2, etc.)
| Method Source | Drivers Included |
|---|---|
getMorphiumInstances() |
InMemory, Pooled |
getMorphiumInstancesNoSingle() |
InMemory, Pooled |
getMorphiumInstancesPooledOnly() |
Pooled only |
getMorphiumInstancesSingleOnly() |
SingleConnect only |
getMorphiumInstancesInMemOnly() |
InMemory only |
getMorphiumInstancesNoInMem() |
Pooled, SingleConnect |
getInMemInstanceOnly() |
InMemory only |
import de.caluga.test.mongo.suite.base.MultiDriverTestBase;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
public class MyFeatureTest extends MultiDriverTestBase {
@ParameterizedTest
@MethodSource("getMorphiumInstances") // Runs with InMemory and Pooled
public void testMyFeature(Morphium morphium) throws Exception {
try (morphium) { // Auto-close when done
// Your test code here
UncachedObject obj = new UncachedObject("test", 1);
morphium.store(obj);
var result = morphium.createQueryFor(UncachedObject.class)
.f("counter").eq(1)
.get();
assertNotNull(result);
assertEquals("test", result.getStrValue());
}
}
}The MultiDriverTestBase respects these system properties:
| Property | Values | Description |
|---|---|---|
morphium.driver |
inmem, pooled, single, all
|
Which drivers to include |
morphium.database |
e.g., morphium_test_slot1
|
Base database name prefix |
morphium.tests.external |
true/false
|
Enable external MongoDB tests |
When morphium.tests.external is not set (default), only InMemoryDriver is used regardless of morphium.driver setting. This allows fast local testing without MongoDB.
TestConfig.java centralizes test configuration with this precedence:
-
System properties (
-Dmorphium.xxx) -
Environment variables (
MORPHIUM_XXX) -
morphium-test.propertiesresource file - Built-in defaults
Key configuration options:
# Connection
morphium.uri=mongodb://localhost:27017/test
morphium.hostSeed=localhost:27017,localhost:27018
morphium.database=morphium_test
# Driver
morphium.driver=pooled # pooled|single|inmem
# Authentication
morphium.user=testuser
morphium.pass=testpass
morphium.authDb=admin
# Timeouts (milliseconds)
morphium.connectionTimeout=2000
morphium.readTimeout=10000
morphium.serverSelectionTimeout=15000The runtests.sh script provides a convenient wrapper around Maven with additional features.
--driver NAME # pooled|single|inmem (default: inmem if no external)
--external # Enable external MongoDB tests--test PATTERN # Run only matching test classes
--tags LIST # Include JUnit 5 tags (comma-separated)
--exclude-tags LIST # Exclude JUnit 5 tags
--rerunfailed # Rerun only previously failed testsAvailable tags: core, messaging, driver, inmemory, aggregation, cache, admin, performance, encryption, jms, geo, util, external, manual, failover, wire-failover
Two tags have special semantics:
-
external— the test needs a real MongoDB (CI-safe). Excluded by default; enabled by--external/ the-PexternalMaven profile. -
manual— the test kills processes or relies on a hardcoded local setup. Never runs in CI: excluded by default, by-Pexternaland byruntests.sh. Run explicitly viamvn -pl morphium-core test -Dtest=<Class> -Dtest.excludeTags=. The remaining process-killing failover tests (SingleConnectDriverFailoverTests,driver/pool/FailoverTests) still carry this tag; the plainfailovertag itself is also used as a catch-all to skip a handful of other tests on PoppyDB phases (pooled-driver tests that need a real MongoDB,SortingTest's slow bulk-write case).
wire-failover is different: it marks DriverFailoverProxyTest, which reproduces failover behaviour (clean stepdown, hard kill, frozen socket, and the resulting read/write/messaging recovery) through a reusable wire-level fault-injection proxy instead of controlling a real replica set process. It needs no hardcoded local setup and kills nothing, so it does run in the normal matrix — against both MongoDB and PoppyDB replica sets — and is not excluded by runtests.sh or any Maven profile.
The proxy behind that test (WireProxy, package de.caluga.test.morphium.testutil.proxy) is a general-purpose test utility, not failover-specific: runtime-switchable fault modes (freeze/reset/close), wire-level frame observation/logging, and response rewriting up to deliberately injecting invalid replies. See Wire Proxy — Fault Injection & Wire-Level Monitoring for the full guide.
--poppydb # Start single-node PoppyDB (recommended)
--poppydb-replicaset # Start 3-node replica set (ports 27017-27019)
# Deprecated aliases: --morphium-server, --morphium-server-replicaset--parallel N # Run tests in N parallel slots (1-16)
--retry N # Retry failed tests N times
--restart # Clear logs and start fresh
--skip # Skip already-run tests (continue mode)--logs NUM # Number of log lines to show
--refresh NUM # Refresh display every NUM seconds
--stats # Show test statistics
--verbose # Enable verbose test output# Fast development cycle - InMemory only
./runtests.sh --driver inmem --test MyNewTest --restart
# Full test against PoppyDB single node
./runtests.sh --poppydb --driver pooled --restart
# Parallel testing for speed
./runtests.sh --driver inmem --parallel 4 --restart
# Test specific tags
./runtests.sh --driver inmem --tags core,messaging --restart
# Rerun failed tests with retries
./runtests.sh --rerunfailed --retry 3
# External MongoDB with authentication
./runtests.sh --external --driver pooled \
--uri mongodb://user:pass@mongo1:27017/test?authSource=admin-
Sequential runs:
test.log/<TestClass>.log -
Parallel runs:
test.log/slot_<N>/<TestClass>.log -
PoppyDB logs:
.poppydb-local/logs/poppydb_<port>.log -
Failed tests summary:
failed.txt
./runtests.sh --driver inmem --test YourTest- No external dependencies
- Fast execution
- Full feature parity for most operations
@ParameterizedTest
@MethodSource("getMorphiumInstances")
public void myTest(Morphium morphium) throws Exception {
try (morphium) { // Ensures cleanup
// test code
}
}// Use TestUtils for waiting
TestUtils.waitForConditionToBecomeTrue(5000, "Data not stored",
() -> morphium.createQueryFor(MyClass.class).countAll() == expectedCount);When testing against replica sets (PoppyDB or MongoDB), data replication takes time:
// Allow time for replication (increase timeout for replica sets)
TestUtils.waitForConditionToBecomeTrue(5000, "Replication timeout",
() -> query.countAll() == expected);MultiDriverTestBase automatically drops test databases before each test run. For additional cleanup within tests:
morphium.dropCollection(MyClass.class);@Tag("core") // Core functionality
@Tag("messaging") // Messaging tests
@Tag("performance") // Slow performance tests
@Tag("external") // Requires external MongoDB
@Tag("inmemory") // InMemory-specific tests// For tests that work with any driver
@MethodSource("getMorphiumInstances")
// For tests requiring real MongoDB features
@MethodSource("getMorphiumInstancesNoInMem")
// For InMemory-specific behavior tests
@MethodSource("getMorphiumInstancesInMemOnly")- Check for infinite loops in wait conditions
- Verify PoppyDB is running (if using
--poppydb) - Check connection timeouts in logs
Replica set tests can be timing-sensitive:
- Increase wait timeouts for replication
- Use
--poppydb(single node) instead of--poppydb-replicasetfor most tests - Run flaky tests with
--retry 2
Each parallel slot uses a unique database prefix. If you see conflicts:
- Ensure tests use
morphiumparameter, not shared static instances - Check that
--restartis used to clear old data - Verify tests close their Morphium instances properly
./runtests.sh --stats # Full statistics
./runtests.sh --stats --noreason # Just test names
cat failed.txt # List of failed testsFor IDE integration or CI pipelines:
# InMemory (default, no external MongoDB needed)
mvn test -Dmorphium.test.driver=inmem
# External MongoDB
mvn test -Pexternal -Dmorphium.driver=pooled \
-Dmorphium.uri=mongodb://localhost:27017/test
# Specific test
mvn test -Dtest=BasicFunctionalityTest -Dmorphium.test.driver=inmem
# With tags
mvn test -Dgroups=core,messaging -DexcludedGroups=performance-
Test Runner Reference - Additional
runtests.shdetails - InMemory Driver - InMemoryDriver specifics
- PoppyDB - PoppyDB (formerly MorphiumServer) documentation