๐ด The Error You're Seeing
Confirm this matches your console output. If it does, you're in the right place.
java.lang.IllegalStateException: Failed to load ApplicationContext
...
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.devinhyderabad.service.UserService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1336)โก Quick Fix Works 80% of the time
Ensure the real implementation class (e.g., UserServiceImpl) is annotated with @Service and is in a scanned package.
@Service
public class UserServiceImpl implements UserService { ... }๐ง Why this Happens
Tap to expand the deep technical explanation
In Spring Boot 3, `@MockBean` works by finding the *real* bean in the application context and replacing it with a Mockito mock. If the real bean doesn't exist (e.g., you forgot the `@Service` annotation, or it's in a non-scanned package), Spring cannot find anything to replace, and throws `NoSuchBeanDefinitionException`.
The HITEC City Parking Spot Analogy:
It's like ordering a fake cake for a movie set. The prop department (Spring) asks the bakery for the real cake recipe to copy it, but the bakery says, 'We don't make that cake.' The prop department can't make a fake version of something that doesn't exist.
๐ How to Reproduce Confirm this is your error
Create a `UserService` interface with no implementations. Write a test using `@MockBean private UserService userService;`. Run the test.
๐ ๏ธ Solutions (5 Ways to Fix)
Create the real implementation
๐ Use this if you wrote the interface but haven't written the implementation yet.
Spring needs the real bean to exist before @MockBean can replace it.
@Service
public class UserServiceImpl implements UserService { ... }Fix Component Scan paths
๐ Use this if the implementation exists, but is in a package outside the main app's scan path.
If your test uses `@SpringBootTest`, it scans from the main Application class package. If the service is in a sibling package, it won't be found.
@SpringBootTest
@ComponentScan(basePackages = "com.devinhyderabad")
class MyTest { ... }Use @Mock instead of @MockBean
๐ Use this if you are writing a pure unit test and don't need to start the Spring context.
If you don't need Spring's dependency injection, use Mockito's `@Mock` and `@InjectMocks`. This doesn't require the real bean to exist.
@ExtendWith(MockitoExtension.class)
class MyTest {
@Mock
private UserService userService; // Doesn't need Spring context
@InjectMocks
private UserController userController;
}Import specific configurations
๐ Use this if you are using a sliced test (like @WebMvcTest) and the service isn't picked up.
Sliced tests don't scan the whole context. You must explicitly import the service class.
@WebMvcTest(UserController.class)
@Import(UserServiceImpl.class)
class UserControllerTest { ... }Provide the bean in a @TestConfiguration
๐ Use this if you want to provide a stubbed implementation just for testing.
Define a test-specific configuration class that creates the missing bean.
@TestConfiguration
public class TestConfig {
@Bean
public UserService userService() {
return new UserService() { /* stub methods */ };
}
}๐ Version Notes
@MockBean sometimes silently registered a new bean if one didn't exist.
Stricter context validation. Fails fast if @MockBean cannot find a real bean to replace.
๐ก๏ธ How to Prevent This Next Time
Use `@MockBean` only to replace existing beans in integration tests. For pure unit tests, prefer Mockito's `@Mock` and `@ExtendWith(MockitoExtension.class)`.