Testing the Service Layer
Fast recall
Quick revision
Core answer
Practical judgment about which test type belongs at which layer of a Spring Boot application.
Using @SpringBootTest for every service test, making the suite very slow without gaining meaningful coverage.
Explain that one service can need focused rule tests plus integration tests for proxies, transactions, persistence, or messaging boundaries
Interview-ready guide
Interview answer
I normally give a service focused unit tests for its validation, calculations, branching, and orchestration rules. I construct a small object graph and use a mock, fake, or real lightweight collaborator according to the contract. I also add integration coverage where the behavior depends on Spring proxies, @Transactional semantics, persistence mappings or queries, events, security, caching, or other infrastructure. That means a service can need both kinds of test. I choose the smallest boundary that proves each requirement and measure suite cost rather than assuming a fixed speed ratio.
Testing the Service Layer
Direct Answer
Use unit tests for service rules that can be proved with a small object graph, and integration tests for behavior that depends on Spring proxies, transactions, persistence mappings, queries, configuration, or other real boundaries. A service often needs both. Mocks are useful at a boundary, but a fake or real lightweight collaborator can be clearer; speed differences must be measured rather than assumed.
Code Example
@ExtendWith(MockitoExtension.class)
class OrderServiceTest {
@Mock private OrderRepository orderRepository;
@InjectMocks private OrderService orderService;
@Test
void shouldCalculateDiscountForLargeOrder() {
var order = new Order(1L, "Laptop", 1500.0);
when(orderRepository.findById(1L)).thenReturn(Optional.of(order));
var discountedPrice = orderService.applyDiscount(1L); // logic under test
assertEquals(1350.0, discountedPrice); // 10% discount
verify(orderRepository).findById(1L); // interaction verified
}
}
Common Mistakes & Pitfalls
- Using @SpringBootTest for local calculations: A broad context can hide the simple behavior under test.
- Mocking the persistence contract everywhere: A mock cannot prove query semantics, mapping, constraints, or transaction behavior.
- Assuming annotations work in a unit test: Calling a service created with
newdoes not apply proxy-based @Transactional, security, or caching behavior.
Check your understanding
Answer these without looking back at the article.
- How do you test that a service method rolls back a transaction on exception?
- What is @InjectMocks and how does it work with @Mock?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.