← Home
☕Java Developer Interview Questions — Fresher to 5 YOEJava Dev InterviewNEW
🧪

Testing, Actuator & Microservices

MockMvc, Testcontainers, Actuator, Eureka/Feign · 8 questions

1

What is the difference between @SpringBootTest, @WebMvcTest, and @DataJpaTest?

Must Know🌱 Fresher
AnnotationLoadsUse for
@SpringBootTestThe full application context (every bean)End-to-end / integration tests exercising real wiring
@WebMvcTestOnly the web layer (controllers, filters, MVC config) — services/repositories are mockedFast, isolated controller tests via MockMvc
@DataJpaTestOnly JPA-related beans (repositories, entity manager), with an in-memory DB by defaultTesting repository queries in isolation
Spring Testing
2

What is MockMvc, and how do you use it to test a controller?

Must Know🌱 Fresher

MockMvc simulates HTTP requests against your controllers without starting a real embedded server — it dispatches directly into the Spring MVC infrastructure, making controller tests fast and able to run without opening any network port.

A MockMvc controller testjava
@WebMvcTest(UserController.class)
class UserControllerTest {
    @Autowired MockMvc mockMvc;
    @MockBean UserService userService;

    @Test
    void returnsUser() throws Exception {
        when(userService.findById(1L)).thenReturn(new User(1L, "Ada"));

        mockMvc.perform(get("/users/1"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.name").value("Ada"));
    }
}
Spring TestingMockMvc
3

What is the difference between @Mock, @Spy, and @MockBean?

Important📊 Mid
  • @Mock (plain Mockito) — a fully fake object; every method returns a default/stubbed value unless you explicitly configure it with when(...).
  • @Spy — wraps a real object; calls go to the real implementation unless you explicitly stub a specific method, useful when you want most behavior real but need to override or verify just one method.
  • @MockBean — a Spring Boot Test annotation, not plain Mockito: it creates a Mockito mock and replaces the matching bean in the Spring ApplicationContext with it, so any other bean that gets it autowired (e.g. a controller under test) receives the mock instead of the real bean.
Spring TestingMockito
4

What are Testcontainers, and why use them instead of an in-memory database like H2?

Important📊 Mid

Testcontainers spins up real Docker containers (Postgres, Kafka, Redis...) for integration tests, then tears them down afterward — giving you a test environment that behaves exactly like production, instead of an approximation.

H2 (an in-memory database) is faster to start and needs no Docker, but it's a different database engine than most production stacks (Postgres/MySQL) — SQL dialect differences, constraint behavior, and vendor-specific features (JSON columns, window functions) can all behave subtly differently, letting bugs slip past tests that pass against H2 but fail against the real database. Testcontainers trades a bit of startup speed for tests that accurately reflect production behavior.

A Postgres Testcontainerjava
@Testcontainers
@SpringBootTest
class OrderRepositoryIT {
    @Container
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16");

    @DynamicPropertySource
    static void props(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", postgres::getJdbcUrl);
    }
}
Spring TestingTestcontainers
5

What is service discovery, and how does Eureka work?

Important📊 Mid

In a microservices architecture, instances scale up/down and get rescheduled to different hosts/ports constantly — hardcoding "order-service is at 10.0.1.5:8080" breaks the moment it moves. Service discovery solves this: each service instance registers itself with a central registry on startup; any other service asks the registry "where is order-service right now?" instead of using a fixed address.

🧭 Eureka registration & discovery
Order Service instance starts
    -> registers itself with Eureka Server: "I'm order-service at 10.0.1.7:8081"
    -> sends periodic heartbeats to stay registered

Payment Service needs to call Order Service:
    -> asks Eureka: "where are the healthy instances of order-service?"
    -> Eureka returns a live list -- Payment Service load-balances across them
    -> if an instance stops sending heartbeats, Eureka evicts it from the list

Add spring-cloud-starter-netflix-eureka-client, point it at the Eureka server's URL, and annotate the main class @EnableEurekaClient (or rely on auto-detection in newer Spring Cloud versions) — registration and heartbeats happen automatically after that.

MicroservicesEureka
6

What is a Feign client, and why use it for inter-service calls?

Important📊 Mid

Feign is a declarative HTTP client — instead of manually building requests with RestTemplate or WebClient (URL strings, headers, response parsing), you declare a Java interface describing the remote API, and Feign generates the implementation at runtime.

A Feign clientjava
@FeignClient(name = "order-service") // resolves via service discovery (e.g. Eureka)
interface OrderClient {
    @GetMapping("/orders/{id}")
    Order getOrder(@PathVariable Long id);
}

// Usage -- looks like a plain local method call:
Order order = orderClient.getOrder(42L);

It integrates natively with service discovery (call by logical service name, not a hardcoded host) and load balancing, and pairs cleanly with resilience libraries (retry, circuit breaker) via simple annotations — which is why it's the conventional default for synchronous inter-service calls in a Spring Cloud microservices stack.

MicroservicesFeign
7

What is a circuit breaker, and why do microservices need one?

Important📊 Mid

A circuit breaker wraps a call to a remote service and tracks its recent failure rate. If failures exceed a threshold, the circuit "opens" — further calls fail immediately (optionally falling back to a default/cached response) without even attempting the network call, for a cooldown period, before "half-opening" to test if the dependency has recovered.

In a microservices architecture, a single slow or failing downstream service can otherwise cause every upstream caller to pile up threads waiting on it, exhausting thread pools and cascading the failure across the whole system. A circuit breaker contains the blast radius: callers fail fast and stay responsive (possibly in a degraded mode) instead of getting dragged down with the failing dependency. See Circuit Breaker / Retry / Bulkhead → for the full pattern (often implemented via Resilience4j in Spring Boot apps).

MicroservicesResilience
8

How do you add a custom health indicator to Spring Boot Actuator?

Optional📊 Mid

Implement HealthIndicator (or extend AbstractHealthIndicator) as a bean — Spring Boot automatically picks it up and folds its result into /actuator/health, alongside built-in checks (disk space, database).

A custom health checkjava
@Component
class PaymentGatewayHealthIndicator implements HealthIndicator {
    public Health health() {
        boolean reachable = paymentClient.ping();
        return reachable ? Health.up().build()
                          : Health.down().withDetail("reason", "gateway unreachable").build();
    }
}

If any indicator reports DOWN, the overall aggregated health status becomes DOWN too — useful for load balancers/orchestrators (Kubernetes readiness probes) deciding whether to route traffic to this instance.

Spring BootActuator