6

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?

oberlies
  • 11,503
  • 4
  • 63
  • 110
  • Check to make sure that TestHelperBean is annotated properly. It should not be a problem if that class is part of the same project. – duffymo Jan 30 '19 at 16:07
  • The TestHelperBean is annotated with `@Component` - see updated question. This is correct AFAIK. – oberlies Jan 31 '19 at 13:48

4 Answers4

9

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.
oberlies
  • 11,503
  • 4
  • 63
  • 110
1

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();
}
shasr
  • 325
  • 2
  • 5
0

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

@ComponentScan({"org.myproject","org.myproject. server","org.myproject. sibilings"})
Ryuzaki L
  • 37,302
  • 12
  • 68
  • 98
-1

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.

Alessandro Power
  • 2,395
  • 2
  • 19
  • 39