首页 > 解决方案 > Spring boot:将测试中的bean注入Web环境

问题描述

我正在为我的示例应用程序构建一些集成测试,并且想知道是否可以在我的测试本身中创建一些测试数据,然后将其注入正在运行的服务器。我不想模拟我的数据,因为我希望我的测试贯穿整个堆栈。

我了解 Spring Boot 文档说服务器和测试在 2 个单独的线程中运行,但是是否可以通过相同的上下文?

我到目前为止的代码:

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ArtistResourceTests {
    @Autowired
    private TestRestTemplate restTemplate;

    @Autowired
    private ArtistRepository artistRepository;

    @Test
    @Transactional
    public void listReturnsArtists() {
        Artist artist = new DataFactory().getArtist();
        this.artistRepository.save(artist);

        ParameterizedTypeReference<List<Artist>> artistTypeDefinition = new ParameterizedTypeReference<List<Artist>>() {};
        ResponseEntity<List<Artist>> response = this.restTemplate.exchange("/artists", HttpMethod.GET, null, artistTypeDefinition);

        assertEquals(1, response.getBody().size());
    }
}

但这会返回 0 个结果而不是 1 个结果。

标签: javaspringspring-bootjunitjunit5

解决方案


我认为您不会与某些远程运行的服务器进行交互。

SpringBootTest注释在测试中本地启动整个微服务。否则,如果您的测试只是对远程服务器的一系列调用,那么您实际上并不需要@SpringBootTest(并且根本不需要 spring boot :))。

所以你在测试中有一个应用程序上下文。现在您要问的是如何预填充数据。这太宽泛了,因为您没有指定数据的确切存储位置以及涉及哪些数据持久层(RDBMS、Elasticsearch、Mongo,...)?

一种可能的通用方法是使用可以具有方法的测试执行侦听器beforeTestMethod

应用程序上下文已启动,因此您可以真正以自定义方式准备数据并将其保存到您选择的数据库中(通过将 DAO 注入侦听器或其他方式)。

如果您使用 Flyway,另一个有趣的方法是在src/test/resources/data文件夹中提供迁移,以便 Flyway 在测试期间自动执行迁移。

更新

评论指出,使用了 H2 DB,在这种情况下,假设数据源配置正确并且确实提供了到 H2 的连接,最简单的方法是运行带有数据插入的 SQL 脚本:

@Sql(scripts = {"/scripts/populateData1.sql", ..., "/scripts/populate_data_N.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
public void myTest() {
...
}

现在,如果您必须与

this.artistRepository.save(artist);

然后 spring 不关心线程。只要“数据”是一个bean(或资源),它就可以注入任何数据,因为您正在使用对象(艺术家),它必须是一个bean。

因此TestConfiguration,使用 bean创建Artist,确保它与 test 在同一个包中(以便 spring boot 测试扫描过程将加载配置)并像往常一样使用 @Autowired 将其注入到测试中:

@TestConfiguration
public class ArtistsConfiguration {

   @Bean 
   public Artist artistForTests() {
       return new Artist(...);
   }
}


@Import(ArtistsConfiguration.class)
@SpringBootTest
public class MyTest {

   @Autowired
   private Artist artist;

   ....
}

推荐阅读