Spring boot field injection with autowire not working in JUnit test
Solution 1
@SpringBootTest
is fairly heavyweight, and for all intents and purpose will load your entire application, https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications, it's fairly heavyweight and dramatically affects test time. Depending on what you are trying to test you may want to look into
- Slice tests e.g.
@JsonTest
,@DataJpaTest
,@WebMvcTest
etc. , https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications-testing-autoconfigured-tests. Benefit of these tests are not only will they not load everything, thus faster, but will try to hunt out the relevant configurations. - Plain old
@ContextConfiguration
and point to the relevant@Configuration
's required to load beans needed for the test https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#contextconfiguration
Solution 2
I replaced
@RunWith(SpringJUnit4ClassRunner.class)
with
@SpringBootTest
@RunWith(SpringRunner.class)
This appears to be working fine: I see Spring boot firing up and loading beans. I'll keep this question open for a short while for better suggestions.
Solution 3
I ran into similar problem where my spring context was not getting initialized and therefore I was not able to inject the bean with @Autowired
annotation. Then I came across this post and tried with the below annotations as suggested by @progonkpa and it started working.
@SpringBootTest
@RunWith(SpringRunner.class)
But then I realized that @SpringBootTest
already contains @ExtendWith({SpringExtension.class})
annotation which is Junit5 equivalent of @RunWith(SpringRunner.class)
thus it should load spring-context while running the test. Then I found out the silly mistake I made to import @Test
annotation from junit4(i.e org.junit.Test;
) instead of junit5(i.e org.junit.jupiter.api.Test;
) library. I changed the @Test
from junit5 library and it started working with a single annotation @SpringBootTest
.
p.s : don't forget to exclude junit4 library from your dependency if you are using junit5
progonkpa
Updated on June 15, 2022Comments
-
progonkpa almost 2 years
I want to inject DeMorgenArticleScraper in a test.
@RunWith(SpringJUnit4ClassRunner.class) public class DeMorgenArticleScraperTest { @Autowired private DeMorgenArticleScraper deMorgenArticleScraper; ... }
The DeMorgenArticleScraper component has some configuration going on for itself, but the IDE/compiler is not complaining about them.
@Component public class DeMorgenArticleScraper extends NewsPaperArticleScraper { @Autowired public DeMorgenArticleScraper( @Qualifier("deMorgenSelectorContainer") SelectorContainer selector, GenericArticleScraper genericArticleScraper, @Qualifier("deMorgenCompany") Company company) { super(selector, genericArticleScraper, company); } ... }
The constructor parameters that are annotated with @Qualifier, are defined in a Config.class With @Bean. The class itself has @Configuration. I figure the problem is not situated here.
The IDE warns me already, no bean found...autowired members must be defined in a bean. But as far as I know, it is defined in a bean with the @Component annotation. All other bean wiring seems ok as the Spring boot application can start (when I comment out the test class).