Unomi 3 · Quality
Faster service unit tests
InMemoryPersistenceServiceImpl — a full PersistenceService on the test classpath so service logic no longer waits on Karaf.
In Unomi 2.x, most confidence meant integration tests: boot Karaf, talk to Elasticsearch (or Docker), wait.
That still matters for the live stack. It is the wrong loop for “does ProfileServiceImpl handle this edge case?”
UNOMI-881 / #772 / #776 added a unit-test harness centered on one class:
services/src/test/java/org/apache/unomi/services/impl/InMemoryPersistenceServiceImpl.java
What it is (and is not)
It is not a production persistence engine. It is a complete PersistenceService implementation living only on the test classpath.
Capabilities
- Full SPI surface — save/load/remove, query (condition + field), range query, paginated
PartialList, remove-by-query - Real condition evaluation —
ConditionEvaluatorDispatcher(not a stubbed query layer) - In-memory store —
ConcurrentHashMapkeyed items; optional JSON file mirror undertarget/persistence-data(pretty-print, clear-on-init) - Refresh simulation — optional refresh delay thread; per-item-type policies
FALSE/TRUE/WAIT_FOR;refresh()API - Scroll — scroll id + time validity like ES/OS style paging
- Default query limit — mirrors search-engine default size when callers pass negative size
- Property mappings — set/get property mapping metadata used by services
- Aggregates — persistence aggregate SPI support used by analytics-style service tests
- Sequences / primary terms — index sequence helpers for ID generation scenarios
- System-item ID conventions — same
tenantId_itemId_itemTyperules as ES/OS for system types (rules, segments, schemas, …) - Tenant transformation listeners — register listeners like production persistence
- Batching / overwrite flags —
save(item, useBatching, alwaysOverwrite)overloads - Lifecycle —
shutdown()to stop refresh threads between tests
How tests use it
Typical Surefire tests construct the harness, wire a real *ServiceImpl, and assert behavior without OSGi:
persistenceService = new InMemoryPersistenceServiceImpl(
executionContextManager, conditionEvaluatorDispatcher);
// then inject into ProfileServiceImpl, EventServiceImpl,
// RulesServiceImpl, SegmentServiceImpl, …
Concrete adopters in-tree include ProfileServiceImplTest, EventServiceImplTest, RulesServiceImplTest, SegmentServiceImplTest, and the self-test InMemoryPersistenceServiceImplTest.
Unit vs integration
| Integration tests | Harness unit tests | |
|---|---|---|
| Speed | Minutes+ | Seconds |
| Isolation | Shared cluster state | Fresh store per test |
| Scope | Full platform | One service / scenario |
| Fidelity | Production ES/OS | SPI + conditions + refresh simulation |
ITs prove the live stack (and pair with the
clearer IT console).
The harness is why Unomi 3 could grow high-signal @Test coverage around services without waiting on Docker every time.