Compare @DataMongoTest with its sibling data slices @DataR2dbcTest, @DataRedisTest, and @DataLdapTest. What does each wire, and what do they share?
answer
- Same skeleton: @OverrideAutoConfiguration(false) + store @AutoConfigure + TypeExcludeFilter
- Mongo→MongoTemplate; R2DBC→DatabaseClient/R2dbcEntityTemplate; Redis→RedisTemplate; LDAP→LdapTemplate
- R2DBC rolls back per test; Mongo/Redis do not
- LDAP → embedded UnboundID; R2DBC → embedded H2 possible
- Two stores at once → @SpringBootTest, not a slice
basics
~20 sEach is a Spring Boot slice that loads only its store's auto-config: @DataMongoTest → Mongo repos + MongoTemplate; @DataR2dbcTest → reactive relational (DatabaseClient/R2dbcEntityTemplate); @DataRedisTest → RedisTemplate + Redis repos; @DataLdapTest → LdapTemplate + LDAP repos. All exclude unrelated beans and disable general auto-config.
solid answer
~40 sThey're one family with identical mechanics but per-store contents. @DataMongoTest wires MongoTemplate/ReactiveMongoTemplate, Mongo repositories, converters, @Document scanning. @DataR2dbcTest wires the reactive relational stack — ConnectionFactory, DatabaseClient, R2dbcEntityTemplate, R2DBC repositories — and is transactional by default (rollback per test) since R2DBC supports transactions, unlike Mongo. @DataRedisTest wires RedisConnectionFactory, RedisTemplate/StringRedisTemplate, and Redis repositories. @DataLdapTest wires LdapTemplate and Spring Data LDAP repositories, and will use an embedded UnboundID LDAP server if that dependency is on the classpath. What they share: each is meta-annotated with @OverrideAutoConfiguration(enabled=false) plus a store-specific @AutoConfigure..., a TypeExcludeFilter to drop @Service/@Controller/@Component, no web/security layer, and reliance on a real backing store (Testcontainers/@ServiceConnection, or embedded where available). Pick the slice matching the datastore under test.
code
java · 26 lines// Reactive relational slice — transactional, rolls back each test
@DataR2dbcTest
class AccountRepositoryTest {
@Autowired AccountRepository repository; // extends ReactiveCrudRepository
@Autowired R2dbcEntityTemplate template;
@Test
void findsByOwner() {
repository.save(new Account("alice", 100)).block();
StepVerifier.create(repository.findByOwner("alice"))
.expectNextCount(1)
.verifyComplete();
}
}
// LDAP slice — embedded UnboundID server if on classpath
@DataLdapTest
class PersonRepositoryTest {
@Autowired PersonRepository repository; // Spring Data LDAP repo
@Autowired LdapTemplate ldapTemplate;
@Test
void findsPerson() {
assertThat(repository.findByCommonName("John Doe")).isNotNull();
}
}go deeper
Know these are per-store test slices and can name what each store's main template bean is.
Explain the shared skeleton and that each wires only its store; know Testcontainers is the usual backing store.
Detail the non-uniform transaction/rollback behavior, embedded options (H2 for R2DBC, UnboundID for LDAP), and reactive specifics of R2DBC.
Define org-wide slice usage, container/embedded strategy per store, and how multi-store flows escalate to @SpringBootTest; manage context-cache fragmentation.
**One design, many stores.** Spring Boot provides a *data slice* per major datastore. They are structurally identical — each is meta-annotated with `@ExtendWith(SpringExtension.class)`, `@BootstrapWith(...DataXxxTestContextBootstrapper)`, `@OverrideAutoConfiguration(enabled = false)` (turns off Boot's general auto-config so only the slice's explicitly listed auto-config runs), `@TypeExcludeFilters(DataXxxTypeExcludeFilter.class)` (excludes your `@Component`/`@Service`/`@Controller`/`@Configuration`), and one or more `@AutoConfigure...` annotations that pull in exactly that store's beans. The web layer and Spring Security are never part of any of them. What differs is *which store's auto-configuration* each activates. **@DataMongoTest** (`...data.mongo`). Activates MongoDB auto-config: `MongoTemplate`, `ReactiveMongoTemplate`, `MappingMongoConverter`/`MongoCustomConversions`, scanning of `@Document` classes, and creation of `MongoRepository`/`ReactiveMongoRepository` interfaces. **Not transactional/rollback by default.** Needs a real Mongo (Testcontainers `MongoDBContainer` + `@ServiceConnection`, or historically embedded Flapdoodle). **@DataR2dbcTest** (`...data.r2dbc`). Activates the *reactive relational* stack: `ConnectionFactory`, `DatabaseClient`, `R2dbcEntityTemplate`, and R2DBC `ReactiveCrudRepository` interfaces. R2DBC is reactive JDBC-equivalent access to relational DBs. Because relational R2DBC supports transactions, this slice **is transactional and rolls back each test by default** (like `@DataJpaTest`/`@DataJdbcTest`), so tests self-clean. Backing store: an R2DBC-capable DB — embedded H2 via `io.r2dbc:r2dbc-h2`, or Testcontainers Postgres with the r2dbc driver. Note: R2DBC has no schema auto-generation like JPA/Hibernate, so you usually supply a schema (`schema.sql`) or Flyway/Liquibase. **@DataRedisTest** (`...data.redis`). Activates Redis auto-config: `RedisConnectionFactory` (Lettuce), `RedisTemplate`, `StringRedisTemplate`, and Spring Data Redis `@RedisHash` repositories. Redis is a key-value store; there's no rollback semantics, so clean keys between tests. Backing store: Testcontainers Redis (a `GenericContainer` on the Redis image, or a Redis module) — there is no standard embedded Redis in Boot, so a container is the norm. **@DataLdapTest** (`...data.ldap`). Activates LDAP auto-config: `LdapTemplate` and Spring Data LDAP repositories (interfaces annotated with `@Entry`). Uniquely, if the **UnboundID** in-memory LDAP dependency (`com.unboundid:unboundid-ldapsdk`) is on the classpath, Boot starts an **embedded LDAP server** for the test and can load an LDIF, so no external server or container is needed — the closest analog to embedded H2 for JPA. **Shared contract (what to remember).** 1. Slice = only that store's auto-config; everything unrelated (web, security, other stores, your services) is excluded. 2. `@Import`/`@TestConfiguration` to add a specific extra bean; don't over-widen. 3. Real backing store required — Testcontainers + `@ServiceConnection` is the uniform modern answer; embedded options exist for R2DBC-H2 and LDAP-UnboundID. 4. Transaction/rollback behavior is **not** uniform: R2DBC (relational) rolls back per test; Mongo and Redis do **not** — plan cleanup accordingly. 5. Context caching applies to all: identical slice config → one reused context. **Selecting.** Match the slice to the store under test. Testing a reactive Postgres repository → `@DataR2dbcTest`. Caching/rate-limit keys in Redis → `@DataRedisTest`. Directory lookups → `@DataLdapTest`. Document persistence → `@DataMongoTest`. If a test needs two stores at once, no single slice fits — use `@SpringBootTest` (or compose auto-configurations), accepting the heavier context.
- Why does @DataR2dbcTest roll back each test by default but @DataMongoTest does not?R2DBC targets relational databases which support ACID transactions, so the slice (like @DataJpaTest) wraps each test in a transaction rolled back afterward for isolation. MongoDB single-node historically lacked general transaction support, so its slice makes no rollback assumption — you clean data yourself.
- You need to test a flow that writes to Mongo and caches in Redis in the same test. Which slice do you use?None — a single data slice wires only one store. Use @SpringBootTest (full context) or explicitly compose both stores' auto-configurations; the slices are intentionally single-store.
- How does @DataLdapTest avoid needing an external LDAP server?If the UnboundID in-memory LDAP SDK is on the classpath, Boot auto-configures an embedded LDAP server for the test (optionally seeded from an LDIF), similar to how embedded H2 serves JPA slices.
saying these in an interview costs you the question
- Claiming all data slices roll back per test
- Thinking one slice can wire two datastores
- Expecting embedded Redis to appear automatically
- Assuming R2DBC auto-creates schema like Hibernate ddl-auto