java 带有自动装配的 Spring Boot 字段注入在 JUnit 测试中不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/44787722/
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-11-03 08:21:17  来源:igfitidea点击:

Spring boot field injection with autowire not working in JUnit test

javaspring-bootjunitdependency-injectionautowired

提问by progonkpa

I want to inject DeMorgenArticleScraper in a test.

我想在测试中注入 DeMorgenArticleScraper。

@RunWith(SpringJUnit4ClassRunner.class)
public class DeMorgenArticleScraperTest {

    @Autowired
    private DeMorgenArticleScraper deMorgenArticleScraper;

    ...
}

The DeMorgenArticleScraper component has some configuration going on for itself, but the IDE/compiler is not complaining about them.

DeMorgenArticleScraper 组件本身有一些配置,但 IDE/编译器并没有抱怨它们。

@Component
public class DeMorgenArticleScraper extends NewsPaperArticleScraper {

    @Autowired
    public DeMorgenArticleScraper(
            @Qualifier("deMorgenSelectorContainer") SelectorContainer selector,
            GenericArticleScraper genericArticleScraper,
            @Qualifier("deMorgenCompany") Company company) {
        super(selector, genericArticleScraper, company);
    }

    ...
}

The constructor parameters that are annotated with @Qualifier, are defined in a Config.class With @Bean. The class itself has @Configuration. I figure the problem is not situated here.

使用@Qualifier 注释的构造函数参数在带有@Bean 的Config.class 中定义。类本身有@Configuration。我想问题不在这里。

The IDE warns me already, no bean found...autowired members must be defined in a bean. But as far as I know, it is defined in a bean with the @Component annotation. All other bean wiring seems ok as the Spring boot application can start (when I comment out the test class).

IDE 已经警告我,没有找到 bean……必须在 bean 中定义自动装配成员。但据我所知,它是在带有 @Component 注释的 bean 中定义的。所有其他 bean 接线似乎都可以,因为 Spring 启动应用程序可以启动(当我注释掉测试类时)。

回答by progonkpa

I replaced

我换了

@RunWith(SpringJUnit4ClassRunner.class)

with

@SpringBootTest
@RunWith(SpringRunner.class)

This appears to be working fine: I see Spring boot firing up and loading beans. I'll keep this question open for a short while for better suggestions.

这似乎工作正常:我看到 Spring Boot 启动并加载 bean。我会暂时保留这个问题以获得更好的建议。

回答by Darren Forsythe

@SpringBootTestis fairly heavyweight, and for all intents and purpose will load your entire application, https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications, it's fairly heavyweight and dramatically affects test time. Depending on what you are trying to test you may want to look into

@SpringBootTest相当重量级,并且出于所有意图和目的将加载您的整个应用程序,https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features- testing-spring-boot-applications,它是相当重量级的并且会极大地影响测试时间。根据您要测试的内容,您可能需要查看

回答by Vladimir

I have the same problem.

我也有同样的问题。

  1. There is service, which I want to inject for testing but I want to test only platformToSql(..)method without launching whole Spring Boot application.

    @Service
    public class ConverterToSqlImpl implements IConverterToSql {
    
        private final ISomeRepository someRepository;
        private final IUtilService utilService;
    
        public ConverterToSqlMainConstructorServiceImpl(
                IWorkerUtilService workerUtilService,
                ISomeRepository someRepository) {
            this.utilService = utilService;
            this.someRepository = someRepository;
        }
    
        @Override
        public String platformToSql(String platformName) {
            return "platform='" + platformName + "'";
        }
    
        @Override
        public String methodWhichUseRepositoryAndUtilBeans() {
            // some code which is not interested us
        }
    }
    
  2. I create test class. It is necessary to mock beans because they are not need for test method.

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = {ConverterToSqlImpl.class})
    //@ContextConfiguration(classes = {ConverterToSqlImpl.class})
    @MockBeans({@MockBean(IUtilService.class), @MockBean(ISomeRepository.class)})
    public class SqlConverterConstructorTest {
    
        @Autowired
        private IConverterToSqlMainConstructorService convertToSql;
    
        @Test
        public void platformTest() {
            String platformSql = convertToSql.platformToSql("PLATFORM_1");
            String expectedSql = "platform='PLATFORM_1'";
            Assert.assertEquals(platformSql, expectedSql);
        }
    }
    
  1. 有服务,我想注入它进行测试,但我只想测试platformToSql(..)方法而不启动整个 Spring Boot 应用程序。

    @Service
    public class ConverterToSqlImpl implements IConverterToSql {
    
        private final ISomeRepository someRepository;
        private final IUtilService utilService;
    
        public ConverterToSqlMainConstructorServiceImpl(
                IWorkerUtilService workerUtilService,
                ISomeRepository someRepository) {
            this.utilService = utilService;
            this.someRepository = someRepository;
        }
    
        @Override
        public String platformToSql(String platformName) {
            return "platform='" + platformName + "'";
        }
    
        @Override
        public String methodWhichUseRepositoryAndUtilBeans() {
            // some code which is not interested us
        }
    }
    
  2. 我创建测试类。模拟 bean 是必要的,因为它们不需要测试方法。

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = {ConverterToSqlImpl.class})
    //@ContextConfiguration(classes = {ConverterToSqlImpl.class})
    @MockBeans({@MockBean(IUtilService.class), @MockBean(ISomeRepository.class)})
    public class SqlConverterConstructorTest {
    
        @Autowired
        private IConverterToSqlMainConstructorService convertToSql;
    
        @Test
        public void platformTest() {
            String platformSql = convertToSql.platformToSql("PLATFORM_1");
            String expectedSql = "platform='PLATFORM_1'";
            Assert.assertEquals(platformSql, expectedSql);
        }
    }
    

@SpringBootTest(classess = {})load to ApplicationContextonly classess which are pointed out in classesssection, notwhole application with all beans will be lauched.

@SpringBootTest(classess = {})ApplicationContext仅加载到classess部分中指出的类,而不是启动包含所有 bean 的整个应用程序。

Also, as alternative to @SpringBootTestwith classes={..}, you can uncomment line with @ContextConfiguration. It is plain old style.

此外,作为@SpringBootTestwith 的替代方法classes={..},您可以取消注释行@ContextConfiguration。这是朴素的旧风格。