Alex R
Alex R

Reputation: 11881

Why removing WebMvcTest annotation from my test in SpringBoot application causes ComponentScan to fail?

I have a test defined with:

@ComponentScan(basePackages = { ... })
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { AppConfig.class })
@WebMvcTest(secure = false)
public class MyTest extends AbstractJUnit4SpringContextTests  {

     @Autowired SomeClass target;

     @Test public void test() { Assert.assertTrue(target != null); } // MCVE

}

Here's my ContextConfiguration class:

@Configuration
public class AppConfig {

    @Bean
    @ConfigurationProperties(prefix = "datasource")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    @Bean
    ServletWebServerFactory servletWebServerFactory() {
        return new TomcatServletWebServerFactory();
    }

}

This test works fine, but it wastes a lot of time in MVC initialization due to the @WebMvcTest annotation. This particular test does not require any MVC functionality. The annotation ended up in there as a result of trial-and-error, to get the @Autowired annotation to work correctly. But now I want to remove it.

So... I went ahead and removed the @WebMvcTest annotation. But then the test fails because apparently the @ComponentScan does not have any effect unless @WebMvcTest is present (which I now remember, is the reason I added it).

Here's the actual error message:

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

I tried adding @SpringBootTest but it made no difference.

If instead, I add @EnableAutoConfiguration, I get a different error:

java.lang.IllegalArgumentException: dataSource or dataSourceClassName or jdbcUrl is required.

What annotation am I missing?

Upvotes: 0

Views: 678

Answers (1)

Randy Casburn
Randy Casburn

Reputation: 14165

EDIT:

Why removing WebMvcTest annotation from my test in SpringBoot application causes ComponentScan to fail?

Because you have not annotated the class in a way that Spring's IoC/Dependency injection can work correctly.

Now that the answer is clear, here are a couple of suggestions for you to try. They may or may not work depending upon how your project and dependencies etc are put together.

END EDIT:

This particular test does not require any MVC functionality.

You should consider using one of the more direct auto-configuration annotations for the your tests if you don't need all of MVC but do want auto configuration. For instance, it appears you are testing with some data system. Perhaps the @DataJpaTest or @JdbcTest annotations would provide a more streamlined approach. These will enable auto configuration (IoC and Dependency injection).

What annotation am I missing?

As written above, the annotation you are missing is @Configuration

This is counter intuitive here because this isn't a configuration class. But without an appropriate annotation that enables Dependency injection to occur, this is the only way to get this to work. Why?

From the docs:

public @interface ComponentScan

  Configures component scanning directives for use with @Configuration classes.

So your choices are:

  1. Use a different auto config annotation as suggested above
  2. Add the @Configuration annotation

Upvotes: 1

Related Questions