Search code examples
springspring-bootdependency-injectionspock

Cant inject Spring dependencies to both Spock and Spring at same time


I'm having troubles with setting up my tests. I'm using latest version of SpringBoot and Spock Framework. First of all, I'm not configuring my beans "traditional" way. All my classes in package except Facade are package-scoped. I'm not using @Component, @Service, etc.

The only one class Im injecting is Repository. Let me show you my Configuration class

@Configuration
class SurveyConfiguration {
    @Bean
    SurveyFacade surveyFacade(SurveyRepository surveyRepository) {
        ConversionUtils conversionUtils = new ConversionUtils();
        SurveyValidator surveyValidator = new SurveyValidator();
        SurveyCreator surveyCreator = new SurveyCreator(surveyRepository, conversionUtils, surveyValidator);
        return new SurveyFacade(surveyCreator);
    }
}

It works fine, I'v tested all scenarios manually (sending POST to certain endpoint). Let me show you example method from SurveyCreator class I want to test.

SurveyDTO createSurvey(final SurveyDTO surveyDTO) throws ValidationException, PersistenceException {
    Survey survey = conversionUtils.surveyToEntity(surveyDTO);
    surveyValidator.validate(survey);        
    Optional<Survey> savedInstance = Optional.ofNullable(surveyRepository.save(survey)); //Will throw NullPtr
    return savedInstance.map(conversionUtils::surveyToDTO)
            .orElseThrow(PersistenceException::new);
}

Like I said, during runtime it works fine. So lets move on to tests

@SpringBootTest
class SurveyFacadeTest extends Specification {
    @Autowired
    private SurveyRepository surveyRepository
    private SurveyFacade surveyFacade = new SurveyConfiguration().surveyFacade(this.surveyRepository)

    def "should inject beans"() {
        expect:
            surveyRepository != null
            surveyFacade != null
    }
    def "should create survey and return id"() {
        given:
           Long id
        when:
            id = surveyFacade.createSurvey(SampleSurveys.validSurvey())
        then:
            id != surveyFacade
    }
}

First test passes, so I understand I got everything ok for tests. But, I'm getting NullPointer in my java code in method I posted above. Looks like SurveyRepository isnt injected into java code during tests, because thats the one that causes this exception... Any ideas how to work around that, to have my Repository injected in both Spring application and Spock tests?


Solution

  • If there are no reasons against, I recommend you to run the test on the "underlying bean" (and not a manually created instance):

    @Autowired
    private SurveyFacade surveyFacade;