Testing

The extension supports two complementary test strategies that can be used side by side in the same test suite.

Strategy MongoDB Startup speed

Dev Services (automatic container)

real MongoDB in Docker

slower (container pull + boot)

InMemDriver via InMemMorphiumTestProfile

in-process, no Docker

fast (JVM only)

Dev Services (automatic MongoDB container)

When morphium.hosts is not set, the extension starts a MongoDB container automatically in test mode. No configuration is required:

@QuarkusTest                            (1)
class ProductRepositoryTest {

    @Inject ProductRepository repository;
    @Inject Morphium morphium;

    @BeforeEach
    void setUp() {
        morphium.dropCollection(ProductEntity.class);
        morphium.ensureIndicesFor(ProductEntity.class);
    }

    @Test
    void savePersistsEntity() {
        var product = new ProductEntity();
        product.setName("Widget");

        var saved = repository.save(product);

        assertThat(saved.getId()).isNotNull();
    }
}
1 Dev Services automatically starts a MongoDB container – nothing else needed.

To customise the container image:

# src/test/resources/application.properties
%test.quarkus.morphium.devservices.image-name=mongo:7

InMemDriver (no Docker)

For tests that should run without Docker, Morphium’s built-in InMemDriver processes all operations inside the JVM. The quarkus-morphium-testing artifact ships a ready-made Quarkus test profile that sets the required configuration overrides.

Dependency

Add quarkus-morphium-testing as a test dependency:

<dependency>
    <groupId>io.quarkiverse.morphium</groupId>
    <artifactId>quarkus-morphium-testing</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <scope>test</scope>
</dependency>

Usage

import de.caluga.morphium.quarkus.testing.InMemMorphiumTestProfile;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.junit.TestProfile;

@QuarkusTest
@TestProfile(InMemMorphiumTestProfile.class)        (1)
class ProductRepositoryInMemTest {

    @Inject ProductRepository repository;
    @Inject Morphium morphium;

    @BeforeEach
    void setUp() {
        morphium.dropCollection(ProductEntity.class);
        morphium.ensureIndicesFor(ProductEntity.class);
    }

    @Test
    void savePersistsEntity() {
        var product = new ProductEntity();
        product.setName("Widget");

        var saved = repository.save(product);

        assertThat(saved.getId()).isNotNull();
    }
}
1 All Morphium operations run in-process; no container is started.

InMemMorphiumTestProfile applies the following configuration overrides:

morphium.driver-name=InMemDriver
morphium.database=inmem-test
quarkus.morphium.devservices.enabled=false

What the InMemDriver supports

The in-memory driver is a full implementation of the Morphium driver interface. It supports:

  • CRUD operations (store, delete, query)

  • Index creation via ensureIndicesFor (no-op, always succeeds)

  • Collection management (dropCollection, clearCollection)

  • Transactions (best-effort – no multi-document atomicity)

  • @Version optimistic locking

The InMemDriver does not support:

  • Aggregation pipelines with complex stages ($lookup, $facet)

  • Geospatial queries

Mixing Both Strategies

Dev Services tests and InMemDriver tests coexist without any extra configuration. Quarkus detects the different @TestProfile on the InMemDriver test classes and restarts the application context once when switching between profiles. All other tests in the same profile group share a single context and start up only once.

ProductRepositoryTest          → @QuarkusTest              → shared Dev Services context
ProductServiceTest             → @QuarkusTest              → shared Dev Services context

ProductRepositoryInMemTest     → @TestProfile(InMemMorphiumTestProfile.class) → separate InMem context
CampaignRepositoryInMemTest    → @TestProfile(InMemMorphiumTestProfile.class) → same InMem context (reused)

The trade-off: InMem tests run faster individually but incur a one-time restart cost when the test runner first encounters the profile. Use InMem tests for pure repository / persistence-layer tests and Dev Services tests for integration tests that require real MongoDB behaviour (e.g. aggregations, TTL indexes).

Test Isolation

Both strategies use the same isolation pattern: drop the collection and recreate indexes before each test.

@BeforeEach
void setUp() {
    morphium.dropCollection(MyEntity.class);    (1)
    morphium.ensureIndicesFor(MyEntity.class);  (2)
}
1 Removes all documents and the collection itself.
2 Re-creates declared indexes – important for unique-constraint tests.

Alternatively, use morphium.clearCollection(MyEntity.class) to delete all documents while retaining the collection and its indexes (faster when index creation is expensive).

Testing Transactions

@MorphiumTransactional requires a replica set. The InMemDriver does not provide true multi-document atomicity, so transaction tests must use Dev Services (replica set is enabled by default — no extra configuration needed).

@QuarkusTest
class OrderServiceTransactionTest {

    @Inject OrderService orderService;
    @Inject Morphium morphium;

    @BeforeEach
    void setUp() {
        morphium.dropCollection(Order.class);
        morphium.dropCollection(Payment.class);
    }

    @Test
    void commitOnSuccess() {
        orderService.placeOrder(new Order("A1"), new Payment(42.0));
        assertThat(morphium.createQueryFor(Order.class).countAll()).isEqualTo(1);
    }

    @Test
    void rollbackOnFailure() {
        assertThrows(RuntimeException.class, () ->
            orderService.placeOrderThatFails(new Order("A2"), new Payment(0.0)));
        assertThat(morphium.createQueryFor(Order.class).countAll()).isEqualTo(0);
    }
}

See Transactions for details on the transaction lifecycle.

Integration Tests

For @QuarkusIntegrationTest (tests running against the packaged application), Dev Services are still available. The container started during the build phase is reused:

import io.quarkus.test.junit.QuarkusIntegrationTest;

@QuarkusIntegrationTest
class ProductResourceIT {

    @Test
    void listProductsReturnsOk() {
        given()
            .when().get("/products")
            .then().statusCode(200);
    }
}

For a complete example of integration tests with the Morphium extension, see the quarkus-morphium-showcase project.

InMemDriver Limitations Reference

Table 1. InMemDriver feature support
Feature Supported Notes

CRUD (store, delete, query)

yes

Full support

Index creation (ensureIndicesFor)

yes

No-op, always succeeds

Collection management (drop, clear)

yes

Full support

@Version optimistic locking

yes

Full support

Simple aggregations ($match, $group, $sort)

partial

Basic stages only

Complex aggregations ($lookup, $facet, $graphLookup)

no

Use Dev Services for these tests

Geospatial queries

no

Use Dev Services

Multi-document transactions

best-effort

No true atomicity — use Dev Services (replica set enabled by default)

Change streams

no

Use Dev Services