7

I want to write a kind of integration test, but only for a specific class. Which means I want all fields in that class to be automatically wired, but neglect any classes inside the same directory.

Is that possible?

Example:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {TestConfig.class})
public class JunitTest {
    @Autowired
    private MyService service;
}

//how to only scan that specific class?
@ComponentScan(basePackageClasses = {MyService.class, MyInjectedService.class})
@Configuration
public class TestConfig {

}


@Service
public class MyService {
    @Autowired
    private MyInjectedService service;
}

Here I want spring to neglect any classes in the same directories as the both basePackageClasses mentioned.

membersound
  • 81,582
  • 193
  • 585
  • 1,120
  • You can find this answer is useful - https://stackoverflow.com/questions/44787722/spring-boot-field-injection-with-autowire-not-working-in-junit-test/59409695#59409695 – Vladimir Dec 19 '19 at 12:24

3 Answers3

4

The classes attributes supported by @ContextConfiguration and @SpringApplicationConfiguration are only required to reference annotated classes; they do not have to be @Configuration classes.

So with that in mind, you should be able to completely forgo component scanning and simply declare your two annotated components as follows:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {MyService.class, MyInjectedService.class})
public class JUnitTest {
    @Autowired
    private MyService service;

    // ...
}

Having said that, if the above is your goal, it might not make any sense to use Spring Boot's testing support. In other words, if MyService and MyInjectedService do not rely on any features of Spring Boot, you can safely replace @SpringApplicationConfiguration with @ContextConfiguration.

Regards,

Sam (author of the Spring TestContext Framework)

Sam Brannen
  • 29,611
  • 5
  • 104
  • 136
  • Except that you have here to provide the implementation in classes array, not the interface. – francois Bernard-Bouissieres Jun 01 '18 at 09:55
  • That's correct. In this example, `MyService` is the implementation. So that's fine. As for `MyInjectedService`, we cannot tell if it's an interface or the concrete implementation based on the example. So I just assumed both _types_ were concrete implementations. – Sam Brannen Jun 01 '18 at 11:58
3

You could make use of filters to customize scanning. There you can extend the ComponentScan Annotation with Attributes like this:

@ComponentScan(
basePackages = {"com.my.package"}, 
useDefaultFilters = false,
includeFilters = {
    @Filter(type = FilterType.ASSIGNABLE_TYPE, value = {MyService.class, MyInjectedService.class})
})
sven.kwiotek
  • 1,459
  • 15
  • 22
2

You can use @Import annotation. It's more readable and shorter than using the @ComponentScan annotation.

import org.springframework.context.annotation.Import;

@Import(value = {MyService.class, MyInjectedService.class})
public class JUnitTest {
    @Autowired
    private MyService service;

    // ...
}
youngminz
  • 1,364
  • 2
  • 14
  • 23