带有自动装配的弹簧启动现场注入在JUnit测试中不起作用

时间:2017-06-27 18:48:11

标签: java spring-boot junit dependency-injection autowired

我想在测试中注入DeMorgenArticleScraper。

@RunWith(SpringJUnit4ClassRunner.class)
public class DeMorgenArticleScraperTest {

    @Autowired
    private DeMorgenArticleScraper deMorgenArticleScraper;

    ...
}

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);
    }

    ...
}

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

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

4 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:3)

我替换了

@RunWith(SpringJUnit4ClassRunner.class)

@SpringBootTest
@RunWith(SpringRunner.class)

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

答案 2 :(得分:1)

我遇到了类似的问题,我的 spring 上下文没有被初始化,因此我无法用 @Autowired 注释注入 bean。然后我看到了这篇文章,并按照@progonkpa 的建议尝试了以下注释,然后它开始工作了。

@SpringBootTest
@RunWith(SpringRunner.class)

但后来我意识到 @SpringBootTest 已经包含 @ExtendWith({SpringExtension.class}) 注释,它是 Junit5 等效于 @RunWith(SpringRunner.class) 因此它应该在运行测试时加载 spring-context。然后我发现了从 junit4(即 @Test)而不是 junit5(即 org.junit.Test;)库导入 org.junit.jupiter.api.Test; 注释所犯的愚蠢错误。我更改了 junit5 库中的 @Test,它开始使用单个注释 @SpringBootTest

p.s : 如果您使用的是 junit5,请不要忘记从您的依赖项中排除 junit4 库

答案 3 :(得分:0)

我有同样的问题。

  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 = {})仅将ApplicationContext部分中指出的类加载到classess中,包含所有bean的整个应用程序将被启动。

此外,作为@SpringBootTest的{​​{1}}的替代方案,您可以取消对classes={..}的注释。这是朴素的旧样式。