Java @ComponentScan 无法使用 spring-boot-starter-test 进行测试

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23701616/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 00:47:41  来源:igfitidea点击:

@ComponentScan not working in test with spring-boot-starter-test

javaspringunit-testingspring-bootcomponent-scan

提问by samoussa.usa

I am attempting to test my @Serviceand @Repositoryclasses in my project with spring-boot-starter-test and @Autowiredis not working for the classes I'm testing.

我正在尝试使用 spring-boot-starter-test测试我@Service@Repository我的项目中的类,但@Autowired不适用于我正在测试的类。

Unit test:

单元测试:

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = HelloWorldConfiguration.class
//@SpringApplicationConfiguration(classes = HelloWorldRs.class)
//@ComponentScan(basePackages = {"com.me.sbworkshop", "com.me.sbworkshop.service"})
//@ConfigurationProperties("helloworld")
//@EnableAutoConfiguration
//@ActiveProfiles("test")
// THIS CLASS IS IN src/test/java/ AND BUILDS INTO target/test-classes
public class HelloWorldTest {

    @Autowired
    HelloWorldMessageService helloWorldMessageService;

    public static final String EXPECTED = "je pense donc je suis-TESTING123";

    @Test
    public void testGetMessage() {
        String result = helloWorldMessageService.getMessage();
        Assert.assertEquals(EXPECTED, result);
    }
}

Service:

服务:

@Service
@ConfigurationProperties("helloworld")
// THIS CLASS IS IN /src/main/java AND BUILDS INTO target/classes
public class HelloWorldMessageService {

    private String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String  message) {
        this.message=message;
    }

}

The commented class annotations on the unit test represent the various things I've tried to get this working. The test and the project packages are in the same package paths and the @ComponentScanworks fine from my entry point (@RestControllerclass with main method). The service @ComponentScan's and @Autowire's fine in my @RestControllerclass in the src/main/java side, but does not in the test. I am required to add it again as a @Beanin my @Configurationclass in order for @Autowiredto work. The class is otherwise in scope just fine and I can reference and instantiate it just fine from the test. The problem appears to be that @ComponentScandoes not appear to correctly traverse multiple entries in my test runner classpath, in this case /target/test-classes and /target/classes.

单元测试上的注释类注释代表了我试图让它工作的各种事情。测试和项目包位于相同的包路径中,并且@ComponentScan从我的入口点(@RestController带有 main 方法的类)开始工作正常。在 src/main/java 端的我的班级中,服务@ComponentScan的 and@Autowire很好@RestController,但在测试中没有。我需要@Bean在我的@Configuration班级中再次添加它@Autowired才能工作。该类在其他范围内很好,我可以从测试中很好地引用和实例化它。问题似乎是@ComponentScan在我的测试运行程序类路径中似乎没有正确遍历多个条目,在本例中为 /target/test-classes 和 /target/classes。

The IDE I am using is IntelliJ IDEA 13.

我使用的 IDE 是 IntelliJ IDEA 13。

UPDATE- here are HelloWorldRs and its config:

更新- 这里是 HelloWorldRs 及其配置:

@RestController
@EnableAutoConfiguration
@ComponentScan
public class HelloWorldRs {

    //    SPRING BOOT ENTRY POINT - main() method
    public static void main(String[] args) {
        SpringApplication.run(HelloWorldRs.class);
    }

    @Autowired
    HelloWorldMessageService helloWorldMessageService;

    @RequestMapping("/helloWorld")
    public String helloWorld() {
        return helloWorldMessageService.getMessage();
    }

}

...

...

@Configuration
public class HelloWorldConfiguration {

    @Bean
    public Map<String, String> map() {
        return new HashMap<>();
    }

    // This bean was manually added as a workaround to the @ComponentScan problem
    @Bean
    public HelloWorldMessageService helloWorldMessageService() {
        return new HelloWorldMessageService();
    }

    // This bean was manually added as a workaround to the @ComponentScan problem
    @Bean
    public HelloWorldRs helloWorldRs() {
        return new HelloWorldRs();
    }
}

回答by Dave Syer

I don't know if this will turn out to be the solution, but don't use the default package (i.e. don't put *.java in "src/main/java" directly), and definitely don't use a @ComponentScanor @EnableAutoConfigurationin the default package. You will end up killing your application on startup as it tries to scan everything on the classpath (including all the Spring libraries).

我不知道这是否会成为解决方案,但不要使用默认包(即不要将 *.java 直接放在“src/main/java”中),并且绝对不要使用@ComponentScan@EnableAutoConfiguration在默认包中。您最终会在启动时杀死您的应用程序,因为它会尝试扫描类路径上的所有内容(包括所有 Spring 库)。

回答by Marwin

First, I'd recommend to use a newer @RunWith(SpringRunner.class)but that makes no difference, it is just shorter (and recommended).

首先,我建议使用更新的@RunWith(SpringRunner.class)但没有区别,它只是更短(并推荐)。

Second, from the @EnableAutoConfigurationI see that you are using spring boot - which is certainly a good thing. There are some good reasons why notto use @ComponentScandirectly. Can you try the following?

其次,从@EnableAutoConfiguration我看到您正在使用 spring boot - 这当然是一件好事。@ComponentScan直接使用有一些很好的理由。您可以尝试以下方法吗?

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes=YourApplication_or_other_Configuration.class)
public class HelloWorldTest {
... etc.