Spring boot can not autowire repository bean for service test class

3.1k Views Asked by At

I am using a mock repository for my application.
Here is snippet how service looks:

@Service
public class WeatherStationService {

    @Autowired
    private WeatherStationRepositoryMock weatherRepository;

Here is repository code:

@Repository
public class WeatherStationRepositoryMock {

    @Getter
    private List<WeatherStation> stations = new ArrayList<>(
            Arrays.asList(
                    new WeatherStation("huston", "Huston station", RandomGenerator.getRandomGeoInformation()),
                    new WeatherStation("colorado", "Colorado station", RandomGenerator.getRandomGeoInformation())
            )
    );

It works fine when I am executing main() with @SpringBootApplication.

However, when I want to run test class:

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = MockConfig.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
public class WeatherStationServiceTest {

    @Autowired
    @Real
    private WeatherStationService weatherService;

It fails with the following stacktrace:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'edu.lelyak.repository.WeatherStationRepositoryMock' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Here is MockConfig content:

@Configuration
public class MockConfig {
    //**************************** REAL BEANS ******************************
    @Bean
    @Real
    public WeatherStationService weatherServiceReal() {
        return  new WeatherStationService();
    }

Real is marker annotation for real instances:

@Retention(RUNTIME)
@Qualifier
public @interface Real {
}

I can fix it with next initialization at service:

@Service
public class WeatherStationService {
    private WeatherStationRepositoryMock weatherRepository = new WeatherStationRepositoryMock();

It works fine.

Why does this happen?
How to fix autowiring for my custom repository class?

1

There are 1 best solutions below

1
On BEST ANSWER

@SpringBootApplication implicitly defines @ComponentScan, which scans all subpackages for beans. When you run a test using MockConfig's, it doesn't scan for beans.

Solution - use @ComponentScan OR define beans in MockConfig

(1) Using @ComponentScan:

@Configuration
@ComponentScan //Make sure MockConfig is below all beans to discover
public class MockConfig {
    @Bean
    @Real
    public WeatherStationService weatherServiceReal() {
        return  new WeatherStationService();
    }
}

(2) or define required beans:

@Configuration
public class MockConfig {
    @Bean
    @Real
    public WeatherStationService weatherServiceReal() {
        return  new WeatherStationService();
    }

    @Bean
    public WeatherStationRepositoryMock weatherStationRepository() {
        return new WeatherStationRepositoryMock()
    }
}