oberlies
oberlies

Reputation: 11723

Spring Boot test doesn't find bean from sibling package

I have a @SpringBootTest annotated test class which wants to make use of a test utility:

package org.myproject.server;

// ...

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class ServerITest {

    private @Autowired TestHelperBean helper;

    // ...
}

This works fine if the TestHelperBean is defined in the same package as the test class (or in a sub-package).

package org.myproject.server;

import org.springframework.stereotype.Component;

@Component
public class TestHelperBean {
    // ...
}

If I move it to a sibling package though, the component is not found:

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

I guess that component scanning by default only looks in the test class' package and sub-packages – but is there a way to override this default? I tried to add the @ComponentScan annotation to my test, but this didn't seem to have any effect:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@ComponentScan("org.myproject")
public class ServerITest {
    // ...
}

Is there a way to use beans from sibling packages in Spring Boot tests?

Upvotes: 6

Views: 14136

Answers (4)

oberlies
oberlies

Reputation: 11723

The @ComponentScan annotation doesn't work if placed on the test class.

This can be done instead:

  • Add a nested class to your test, and annotate that class with @Configuration and the @ComponentScan annotation.
  • Use an @Import annotation on the test class. Note that @Import only allows to add individual classes to the context.
  • If don't mind adding the classes from the sibling package in other situations as well, you can also place the @ComponentScan annotation on any @Configuration class (or @Component, @Service, etc.) that is already included in the context.

Upvotes: 10

Alessandro Power
Alessandro Power

Reputation: 2472

The other answers regarding the use of ComponentScan are correct. However, the Spring Boot documentation strongly advises that "your main application class be in a root package above other classes". From personal experience I can say that deviating from this practice will result in more trouble than it's worth.

Upvotes: 0

shasr
shasr

Reputation: 375

With componentscan annotation you can specify '*' to cover all subpackages under base package as well.

@ComponentScan({"org.myproject.*", "org.newproj.*"})

It covers all subpackages under "org.myproject" and "org.newproj".

Example package structure

org.myproject 
org.myproject.abc 
org.myproject.abcd 
org.myproject.xyz.abc

org.newproj 
org.newproj.abc 
org.newproj.xyz

OR

Register bean with Configuration/SpringBootApplication class

@Bean
private TestHelperBean helper() {
    return new TestHelperBean();
}

Upvotes: 1

Ryuzaki L
Ryuzaki L

Reputation: 39998

In the component scan you can add multiple packages the need to be scanned

@ComponentScan({"org.myproject","org.myproject. server","org.myproject. sibilings"})

Upvotes: 0

Related Questions