簡體   English   中英

Spring Boot:將測試中的 bean 注入 Web 環境

[英]Spring boot: Inject beans from tests into web environment

我正在為我的示例應用程序構建一些集成測試,並且想知道是否可以在我的測試中創建一些測試數據,然后將其注入正在運行的服務器。 我不想模擬我的數據,因為我希望我的測試在整個堆棧中運行。

我知道 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 個結果。

我認為您不會與某些遠程運行的服務器進行交互。

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。

因此,使用 bean Artist創建TestConfiguration ,確保它與 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;

   ....
}

您可以使用@ContextConfiguration,如下所示:

@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("test")
@ContextConfiguration(locations = {"/testApplicationContext.xml"})
public class TestGetPerson {

    @Autowired
    private PersonService personService;
...

然后在 testApplicationContext 中指定 Spring 應該掃描的包:

<context:component-scan base-package="nl.example.server.service"/>
<context:component-scan base-package="nl.example.server.test.db"/>

可能有一個注釋可以實現相同的目的。 我所做的是使 Spring 掃描大多數包與實時應用程序中的相同,除了數據庫組件:我使用內存中的 H2 數據庫進行測試。 Profiles 注釋告訴 Spring 在測試中要使用哪些類。 此外,您可以配置(在掃描包中使用@Configuration)某些類作為 Mockito 模擬:

@Configuration
@Profile("test")
public class CustomerManagerConfig {
@Bean("customerManager")

    public CustomerManager customerManager() {
        return Mockito.mock(CustomerManager.class);
    }
}

這不會針對單獨的服務器運行您的測試數據,但它會在與您的應用程序環境盡可能相似的環境中運行測試。

關於您的問題,您可以創建自己的模擬,將測試數據注入您喜歡的任何組件中,而不是使用 Mockito 模擬。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM