Chaturmind
LearnDSASystem DesignInterview PrepDevOpsEngineering GrowthBlog
Start learning
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML
  • DevOps
  • Engineering Growth
  • Java Interview Prep

Company

  • Blog
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.


← Java Interview Prep: 5–8 Years

Revise the 2–5 Years Tier

  • Revise: Core Java & Java 8+ (2–5 Years Tier)
  • Revise: Multithreading & Concurrency (2–5 Years Tier)
  • Revise: Spring Framework, Spring Boot & Security (2–5 Years Tier)
  • Revise: Kafka, Git/Maven/Gradle, Deployment & Testing (2–5 Years Tier)

Advanced Core Java

  • Advanced OOP & Design Scenarios — Interview Questions
  • Advanced Concurrency, Collections & Memory — Interview Questions
  • Modern Java Language Features & Annotations — Interview Questions
  • Class Loading, Reflection, Serialization & Idioms — Interview Questions

Java Design Patterns in Depth

  • Design Patterns Overview & Singleton — Interview Questions
  • Factory & Abstract Factory Patterns — Interview Questions
  • Builder & Prototype Patterns — Interview Questions
  • Adapter & Bridge Patterns — Interview Questions
  • Composite & Decorator Patterns — Interview Questions
  • Facade & Proxy Patterns — Interview Questions
  • Chain of Responsibility & Observer Patterns — Interview Questions
  • Strategy & Template Method Patterns — Interview Questions
  • Command Pattern — Interview Questions

Advanced Spring Boot

  • Logging, Configuration & Actuator (Advanced) — Interview Questions
  • Transactions, Multiple Datasources & Query Tuning — Interview Questions
  • Validation & REST API Design (Advanced) — Interview Questions
  • Reactive, Async & Scheduling in Spring Boot — Interview Questions
  • Deployment, High Availability, Scaling & Caching — Interview Questions
  • Custom Starters, DI, Testing & DevTools — Interview Questions

Spring Security for APIs

  • Securing REST APIs End to End — Interview Questions

Microservices at Scale

  • Monolith Migration, Communication & Spring Cloud — Interview Questions
  • Data Consistency, Sagas & Kafka Messaging — Interview Questions
  • Tracing, Discovery, Load Balancing, Service Mesh & Resilience — Interview Questions
  • Deployment, Scaling & Security for Microservices — Interview Questions

Microservice Design Patterns

  • API Gateway, Circuit Breaker & Retry Patterns — Interview Questions
  • Service Discovery & Database per Service Patterns — Interview Questions
  • Saga, Choreography & Orchestration Patterns — Interview Questions
  • Bulkhead & Strangler Fig Patterns — Interview Questions
Chaturmind
← Java Interview Prep: 5–8 Years

Revise the 2–5 Years Tier

  • Revise: Core Java & Java 8+ (2–5 Years Tier)
  • Revise: Multithreading & Concurrency (2–5 Years Tier)
  • Revise: Spring Framework, Spring Boot & Security (2–5 Years Tier)
  • Revise: Kafka, Git/Maven/Gradle, Deployment & Testing (2–5 Years Tier)

Advanced Core Java

  • Advanced OOP & Design Scenarios — Interview Questions
  • Advanced Concurrency, Collections & Memory — Interview Questions
  • Modern Java Language Features & Annotations — Interview Questions
  • Class Loading, Reflection, Serialization & Idioms — Interview Questions

Java Design Patterns in Depth

  • Design Patterns Overview & Singleton — Interview Questions
  • Factory & Abstract Factory Patterns — Interview Questions
  • Builder & Prototype Patterns — Interview Questions
  • Adapter & Bridge Patterns — Interview Questions
  • Composite & Decorator Patterns — Interview Questions
  • Facade & Proxy Patterns — Interview Questions
  • Chain of Responsibility & Observer Patterns — Interview Questions
  • Strategy & Template Method Patterns — Interview Questions
  • Command Pattern — Interview Questions

Advanced Spring Boot

  • Logging, Configuration & Actuator (Advanced) — Interview Questions
  • Transactions, Multiple Datasources & Query Tuning — Interview Questions
  • Validation & REST API Design (Advanced) — Interview Questions
  • Reactive, Async & Scheduling in Spring Boot — Interview Questions
  • Deployment, High Availability, Scaling & Caching — Interview Questions
  • Custom Starters, DI, Testing & DevTools — Interview Questions

Spring Security for APIs

  • Securing REST APIs End to End — Interview Questions

Microservices at Scale

  • Monolith Migration, Communication & Spring Cloud — Interview Questions
  • Data Consistency, Sagas & Kafka Messaging — Interview Questions
  • Tracing, Discovery, Load Balancing, Service Mesh & Resilience — Interview Questions
  • Deployment, Scaling & Security for Microservices — Interview Questions

Microservice Design Patterns

  • API Gateway, Circuit Breaker & Retry Patterns — Interview Questions
  • Service Discovery & Database per Service Patterns — Interview Questions
  • Saga, Choreography & Orchestration Patterns — Interview Questions
  • Bulkhead & Strangler Fig Patterns — Interview Questions
HomeLearnJava Interview PrepJava Interview Prep: 5–8 YearsAdvanced Spring Boot
✓ FreeAdvanced· 10 min read

Custom Starters, DI, Testing & DevTools — Interview Questions

Building a custom Spring Boot starter (autoconfigure + starter modules, AutoConfiguration.imports, conditions, @ConfigurationProperties), wrapping a third-party library as a starter, common starters, alternatives to field @Autowired, @Mock vs @MockBean/@MockitoBean, JUnit 4 vs 5, lifecycle annotations in practice, controller slice tests with MockMvc, integration tests against external APIs (WireMock/MockRestServiceServer/Testcontainers), and DevTools in development vs production.

Published September 25, 2026


How to use this lesson

These questions check whether you build platform pieces (starters) and test properly. Use current APIs:

  • Boot 2.7 and later register auto-configurations in AutoConfiguration.imports, not spring.factories.
  • Boot 3.4 deprecates @MockBean in favour of @MockitoBean.
  • JUnit 5's lifecycle annotations are @BeforeEach and @AfterEach, not @Before and @After.

Q1. How do you create a custom Spring Boot starter, and why is it useful?

Short answer: A starter packages dependencies + auto-configuration + defaults, so any team adds one dependency and gets a correctly configured feature. The convention is two modules:

  1. acme-audit-spring-boot-autoconfigure: the @AutoConfiguration classes, @ConfigurationProperties, and conditions.
  2. acme-audit-spring-boot-starter: an (almost) empty module that depends on the autoconfigure module and on the library itself.

Register the auto-configuration in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports.

@AutoConfiguration
@ConditionalOnClass(AuditClient.class)                                // only when the library is present
@EnableConfigurationProperties(AuditProperties.class)
@ConditionalOnProperty(prefix = "acme.audit", name = "enabled", havingValue = "true", matchIfMissing = true)
public class AuditAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean                                         // the application can override it
    AuditClient auditClient(AuditProperties props) {
        return AuditClient.builder().endpoint(props.endpoint()).timeout(props.timeout()).build();
    }
}

@ConfigurationProperties("acme.audit")
public record AuditProperties(URI endpoint, @DefaultValue("2s") Duration timeout, @DefaultValue("true") boolean enabled) { }
# src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.acme.audit.autoconfigure.AuditAutoConfiguration

Key points to cover:

  • Why it's useful:
    • Company-wide standards (logging, security, tracing, clients) configured once.
    • Consistency.
    • Upgrades done in one place.
    • Less boilerplate.
  • Good practice:
    • Make every bean back off with @ConditionalOnMissingBean.
    • Add spring-boot-configuration-processor, so IDEs autocomplete your properties.
    • Test with ApplicationContextRunner.
    • Never use component scanning inside a starter.

Common trap: the source says to register in spring.factories. That was removed for auto-configurations in Boot 3. Use AutoConfiguration.imports.

Learn it in depth → Auto-Configuration Mechanism

Q2. Your project needs to integrate a third-party library. How would you make a starter for it?

Short answer:

  1. Create the autoconfigure and starter modules, with the library as a dependency (optional in the autoconfigure module).
  2. Expose the library's settings as typed @ConfigurationProperties with safe defaults.
  3. Define its client beans in an @AutoConfiguration, guarded by:
    • @ConditionalOnClass (the library is on the classpath);
    • @ConditionalOnProperty (a feature toggle);
    • @ConditionalOnMissingBean (the user can override it).
  4. Integrate with the platform: Micrometer metrics, health indicators (@ConditionalOnEnabledHealthIndicator), tracing, and customizer interfaces (AuditClientCustomizer) for tweaks.
  5. Order it with @AutoConfiguration(after = …) if it depends on other auto-configurations.
  6. Test the combinations with ApplicationContextRunner, then publish to your artifact repository, with a BOM for versions.
new ApplicationContextRunner()
    .withConfiguration(AutoConfigurations.of(AuditAutoConfiguration.class))
    .withPropertyValues("acme.audit.endpoint=http://localhost:9999")
    .run(ctx -> assertThat(ctx).hasSingleBean(AuditClient.class));

Q3. Name some common Spring Boot starters.

Short answer:

  • Web: spring-boot-starter-web (MVC + Tomcat), -webflux (Reactor + Netty).
  • Data: -data-jpa, -jdbc, -data-mongodb, -data-redis.
  • Security: -security, -oauth2-resource-server, -oauth2-client.
  • Validation and operations: -validation, -actuator.
  • Messaging: -amqp, spring-kafka (not a starter, but auto-configured).
  • Caching and templates: -cache, -thymeleaf, -mail.
  • Test: -test (JUnit 5, Mockito, AssertJ, MockMvc, JSONassert).
  • Others: spring-boot-docker-compose and -testcontainers for local development and tests.

Starters are curated dependency sets, with versions managed by Boot's BOM. The auto-configuration they trigger lives in spring-boot-autoconfigure.

Q4. What are the alternatives to @Autowired?

Short answer:

  • Constructor injection (recommended): a single constructor needs no annotation, since Spring 4.3. Dependencies are final, the object is fully initialised, it's easy to test with new, and circular dependencies are exposed.
  • Setter injection: for optional dependencies, or reconfigurable ones.
  • Jakarta @Inject (JSR-330), and @Resource (by name).
  • ObjectProvider<T>: lazy or optional lookup, or several candidates.
  • @Bean method parameters in configuration classes.
@Service
@RequiredArgsConstructor                       // Lombok generates the constructor; no @Autowired anywhere
class OrderService {
    private final OrderRepository orders;
    private final ObjectProvider<FraudChecker> fraudChecker;   // optional
}

Common trap: "constructor injection doesn't rely on Spring annotations" is only true if you don't annotate. The real reasons to prefer it are immutability, completeness and testability. Field injection hides dependencies, and needs reflection in tests.

Learn it in depth → Dependency Injection

Q5. What's the difference between @Mock and @MockBean (@MockitoBean)?

Short answer:

  • @Mock (Mockito): creates a mock in a plain unit test, with no Spring context. It's injected with @InjectMocks, or manually. It's fast.
  • @MockBean: replaces or adds a bean inside the Spring ApplicationContext for slice or integration tests (@WebMvcTest, @SpringBootTest). It's deprecated in Boot 3.4, in favour of Spring Framework's @MockitoBean (and @MockitoSpyBean).

Key points to cover:

  • Every distinct set of mocked beans creates a new application context, which defeats context caching and slows the test suite. Prefer unit tests with @Mock, and standardise the mocks in slice tests.

Q6. What's the difference between JUnit 4 and JUnit 5, and why choose one?

Short answer:

  • Architecture: JUnit 5 is Platform (the launcher) + Jupiter (the new API) + Vintage (runs JUnit 4 tests).
  • Extensibility: JUnit 4 had @RunWith and @Rule. JUnit 5 has one extension model (@ExtendWith), and several extensions can compose.
  • Features:
    • @ParameterizedTest with rich sources;
    • @Nested, @DisplayName, @Tag;
    • dynamic tests;
    • assertThrows, assertAll, assertTimeout;
    • conditional execution;
    • parallel execution;
    • test instance lifecycle control.
  • Annotations: @Before/@After/@BeforeClass/@AfterClass became @BeforeEach/@AfterEach/@BeforeAll/@AfterAll. @Ignore became @Disabled.

Choose JUnit 5 (or JUnit 6, which requires Java 17+) for anything new. Boot 2.2+ defaults to it. Keep JUnit 4 only for legacy suites, run through Vintage while migrating.

Q7. How would you use the test lifecycle annotations in a practical test?

Short answer:

  • @BeforeAll: expensive, shared, read-only setup, once per class. It's static unless you use @TestInstance(PER_CLASS). For example, start a Testcontainers database, or load reference data.
  • @BeforeEach: fresh state per test: new objects, reset mocks, insert test data. That keeps tests independent and order-free.
  • @AfterEach: clean up per-test side effects: delete rows (or roll back with @Transactional tests), delete temporary files, clear caches and the MDC.
  • @AfterAll: release the shared resources.
@Testcontainers
@SpringBootTest
class OrderRepositoryIT {
    @Container @ServiceConnection
    static PostgreSQLContainer<?> db = new PostgreSQLContainer<>("postgres:16");   // started once (like @BeforeAll)

    @Autowired OrderRepository orders;

    @BeforeEach void seed() { orders.save(Order.pending(customerId, items)); }
    @AfterEach  void clean() { orders.deleteAll(); }

    @Test void findsPendingOrders() { assertThat(orders.findByStatus(PENDING)).hasSize(1); }
}

Common trap: the source uses the JUnit 4 names @Before and @After next to JUnit 5's @BeforeAll. In JUnit 5, use @BeforeEach and @AfterEach. Mixing the two APIs means the JUnit 4 annotations are silently ignored by Jupiter.

Q8. How do you write unit tests for Spring Boot controllers?

Short answer: Use @WebMvcTest(ProductController.class). It loads only the MVC slice: the controller, the advice, converters, filters and security. Then inject MockMvc (or MockMvcTester in Boot 3.4+), and mock the service with @MockitoBean. Assert the status, JSON body, headers and validation errors, without starting a server.

@WebMvcTest(ProductController.class)
class ProductControllerTest {
    @Autowired MockMvc mvc;
    @MockitoBean ProductService service;

    @Test
    void createReturns201WithLocation() throws Exception {
        given(service.create(any())).willReturn(new ProductDto(ID, "Pen", new BigDecimal("20")));
        mvc.perform(post("/products").contentType(APPLICATION_JSON).content("""
                {"name":"Pen","price":20,"stock":5,"sku":"PEN-0001"}"""))
           .andExpect(status().isCreated())
           .andExpect(header().string("Location", endsWith("/products/" + ID)))
           .andExpect(jsonPath("$.name").value("Pen"));
    }

    @Test
    void invalidBodyReturns400() throws Exception {
        mvc.perform(post("/products").contentType(APPLICATION_JSON).content("{\"name\":\"\"}"))
           .andExpect(status().isBadRequest())
           .andExpect(jsonPath("$.errors[*].field", hasItem("name")));
        then(service).shouldHaveNoInteractions();
    }
}

Key points to cover:

  • With Spring Security on the classpath, the slice applies security. Use @WithMockUser or .with(jwt()), and .with(csrf()) for form posts.
  • For a pure unit test of the controller logic, you can also construct the controller with mocks, but then you don't test the mappings, validation or serialisation.

Q9. How would you set up integration tests for an application that calls an external API?

Short answer: Test your real HTTP client code against a fake server, rather than mocking the client bean away (which the source suggests, and which skips serialisation, headers, timeouts and error mapping):

  • WireMock (or MockWebServer): run a stub HTTP server, point the client's base URL at it with @DynamicPropertySource, and stub the responses, including error and latency cases: 500s, timeouts, malformed bodies. That verifies retries, circuit breakers and fallbacks.
  • MockRestServiceServer, for RestTemplate/RestClient bound through @RestClientTest: a lighter, in-JVM version.
  • Contract tests (Spring Cloud Contract or Pact) keep your stubs honest against the provider's real API.
  • Testcontainers for your own infrastructure (database, Kafka, Redis) in the same test.
  • Keep a few smoke tests against the provider's sandbox, run separately (nightly), not on every build.
@SpringBootTest
@WireMockTest(httpPort = 9561)
class ShippingClientIT {
    @DynamicPropertySource
    static void props(DynamicPropertyRegistry r) { r.add("shipping.base-url", () -> "http://localhost:9561"); }

    @Autowired ShippingClient client;

    @Test
    void mapsCarrierTimeoutToUnavailable() {
        stubFor(get(urlPathEqualTo("/rates")).willReturn(aResponse().withFixedDelay(3_000)));
        assertThatThrownBy(() -> client.rates(PARCEL)).isInstanceOf(ShippingUnavailableException.class);
    }
}

@MockitoBean on the client is fine for tests whose focus is elsewhere, such as service logic.

Q10. What should you consider about DevTools in production?

Short answer: Don't ship it.

  • DevTools is disabled automatically when the application runs from a fully packaged JAR (java -jar), or when it detects a production-like launch.
  • Declare it developmentOnly (Gradle) or <optional>true</optional> (Maven), so it's excluded from the repackaged artifact.
  • Risks if it's enabled:
    • Restart classloaders and file watching waste CPU and memory.
    • Caching (for example, templates) is disabled, which hurts performance.
    • Remote DevTools (spring.devtools.remote.secret) is a remote code-update endpoint, and a serious security hole if exposed.
  • Verify in CI that the production image contains no spring-boot-devtools jar.

Q11. How does DevTools help when you're making frequent changes and need immediate feedback?

Short answer:

  • Automatic restart: when classes change (on IDE build), the application restarts quickly using two classloaders. Third-party jars stay loaded, and only your code reloads. That takes seconds, instead of a full cold start.
  • LiveReload: refreshes the browser for template and static changes. Static resources don't trigger a restart at all.
  • Development defaults: template caching off, debug logging for web requests, H2 console enabled.
  • Global settings in ~/.config/spring-boot/.
  • Docker Compose support: spring-boot-docker-compose starts your dependencies on application start.

Key points to cover:

  • For even faster feedback, combine DevTools with Testcontainers at development time (TestApplication with @ServiceConnection), and with hot-swap agents (JRebel, or the JetBrains Runtime's enhanced HotSwap), where available.

Follow-up questions this topic invites — and their answers

Q: What's the difference between @SpringBootTest, @WebMvcTest and @DataJpaTest? A: @SpringBootTest loads the full context (optionally with a real server: webEnvironment = RANDOM_PORT). Slices load only part of it:

  • @WebMvcTest: the MVC layer;
  • @DataJpaTest: JPA repositories, an embedded or Testcontainers database, and transactional rollback per test;
  • also @JsonTest, @RestClientTest, @DataMongoTest.

Slices are faster, and more focused.

Q: How do you keep a Spring test suite fast? A: Maximise context caching: consistent configuration, few distinct @MockitoBean sets, and no @DirtiesContext unless necessary. Favour plain unit tests, reuse Testcontainers through singleton containers, and run the tests in parallel where they're isolated.

Q: How do you override an auto-configured bean from a starter? A: Define your own bean of the same type. @ConditionalOnMissingBean makes the starter back off. Or set properties or use the customizer beans the starter exposes. To disable it entirely, use spring.autoconfigure.exclude.

Q: What does @ServiceConnection do? A: Available since Boot 3.1, it lets a Testcontainers container automatically provide the connection details (URL, username, password) to the matching auto-configuration. It replaces most @DynamicPropertySource boilerplate.

Previous

Deployment, High Availability, Scaling & Caching — Interview Questions

Next

Securing REST APIs End to End — Interview Questions

AI Tutor

Lesson: Custom Starters, DI, Testing & DevTools — Interview Questions

Quick actions

AI responses can be inaccurate. Verify critical information.