Spring Boot 测试不会自动装配所有依赖项

Posted

技术标签:

【中文标题】Spring Boot 测试不会自动装配所有依赖项【英文标题】:Spring boot test doesn't Autowire all dependencies 【发布时间】:2021-10-19 06:43:24 【问题描述】:

我的测试场景中有一些令人困惑的错误。 我们想重构一个根本没有经过测试的应用程序。为确保重构后我们有相同的结果,我将为一个 Controller 类编写一些集成测试。

@RestController
@RequestMapping("/rfq")
public class RfqController 

    @Autowired
    private RfqRepository rfqRepo;

    @Autowired
    private RfqDao rfqDao;
    ...

    @PostMapping("/get")
    public @ResponseBody BuyerRfqView getRFQ(@RequestBody SingleIdBody body) 
        int id = body.getId();
        Optional<Rfq> rfq = rfqRepo.getById(id);
        ...
    

在这种情况下,我想使用 testcontainers 和 spring-boot-test 进行测试,一切正常,容器已启动并运行,应用程序启动至今。但问题是在运行时 spring-boot-test 在被测类中没有Autowire rfqRepo。在 Testclass 中,每个依赖项都在 ComponentScan 或 EntityScan 中,并且存储库也被注入。我不知道为什么这不起作用。当测试运行时,我通过 rfqRepo 得到一个 Nullpointer Exception ... 这是测试类:

@SpringBootTest(classes = RfqController.class, webEnvironment =
SpringBootTest.WebEnvironment.RANDOM_PORT)
@ComponentScan(...)
@EnableJpaRepositories(...)
@EntityScan(...)
@EnableAutoConfiguration
@ActiveProfiles("local")
@Testcontainers
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class RfqControllerTest 

    @Container
    private static OracleContainer database = new OracleContainer(
        "oracleinanutshell/oracle-xe-11g:latest")
        .withExposedPorts(1521, 5500)
        .withPassword("...");
    @InjectMocks
    RfqController rfqController;
    @DynamicPropertySource
    static void databaseProperties(DynamicPropertyRegistry registry) 
        registry.add("spring.datasource.url", database::getJdbcUrl);
        registry.add("spring.datasource.username", database::getUsername);
        registry.add("spring.datasource.password", database::getPassword);
    
    @BeforeEach
    void setUp() 
        MockitoAnnotations.openMocks(this);
        ScriptUtils.runInitScript(new JdbcDatabaseDelegate(database, ""), "ddl.sql");
    
    @Test
    void testGetRFQ() 
        BuyerRfqView result = rfqController.getRFQ(new SingleIdBody(176501));
        Assertions.assertEquals(new BuyerRfqView(), result);
    

【问题讨论】:

如果我看到 EntityScan、ComponentScan 等。我总是质疑这是否正确?为什么父包中没有SpringBootApplication类以及下面的其他所有内容? 这是个好问题 :) ...它是一个古老的项目,因此由于历史原因 :)。 但不幸的是,当我没有使用 injectMocks 而是使用 Autowired 对其进行注释时,我遇到了另一个错误:ScopeNotActiveException 这看起来像是一个“简单”测试的很多注释。您可能需要检查 Spring Boot Test 切片,这些切片可以使设置工作量更小且更易于理解:stevenschwenke.de/springTestSlices 【参考方案1】:

在 SpringBootTest 注解中,您仅使用 RfqController。这是测试期间唯一可用的类。

@SpringBootTest(classes = RfqController.class, webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)

因此,您必须添加测试所需的所有类。

【讨论】:

我是这么认为的,但不幸的是这并不能解决问题。它在运行时也为空 如果你删除“classes = RfqController.class”?

以上是关于Spring Boot 测试不会自动装配所有依赖项的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 测试不启动上下文或加载依赖项

Kotlin Spring Boot 单元测试 - 添加 @TestExecutionListeners 不会注入依赖项

springBoot起步依赖开发流程

使用限定符注入自动装配的依赖项失败

Spring Boot 单元测试自动装配

通过注解实现自定义Spring Boot Starter自动装配