簡體   English   中英

@BeforeAll JUnit/spring-boot-test 在應用程序上下文啟動時運行的替代方案

[英]@BeforeAll JUnit/spring-boot-test alternative that runs when application context starts

我正在編寫一個利用嵌入式數據庫的@Repository/@Service集成測試。 在我的測試課中,我想用一些數據預加載我的數據庫。

我目前正在使用@BeforeEach加載我的示例數據,但是,此代碼在我班級的每個測試中運行。

有什么方法可以在 Spring 應用程序上下文加載之后但在任何測試運行之前加載我的測試數據?

我目前的做法:

@BeforeEach
public void before() {
    repository.save(...); // -> prepopulates repository with sample data
}

@Test
public void testService() {
    service.get(...); // -> gathers existing record
}

@Test
public void deleteById() {
    service.delete(...); // -> deletes existing record
}

但是......有了這個,我需要在每次測試后刷新記錄。 否則很容易違反任何唯一約束。

而不是使用@BeforeEach需要在每次測試之前運行......是否可以在加載 spring 應用程序上下文之后以@BeforeAll類型的方式加載它?

只需將以下代碼段添加到您的代碼中。 這就像您可以檢測Spring應用程序是否真的啟動一樣。

@Configuration
public class AppConfig implements ApplicationListener<ApplicationReadyEvent> {

    /**
     * This is to indicate in the logs when the application has actually started and everything is loaded.
     */
    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        ApplicationContext context = event.getApplicationContext();
        Environment env = context.getEnvironment();
        // do what you want on application start
    }
}

PS對於測試中的數據庫操作, @Sql是評論中提到的最佳候選者。

在加載 Spring 應用程序上下文后,有什么方法可以加載我的測試數據

基本上是的,我認為你可以這樣做:

這個想法是在應用程序上下文啟動或正在啟動的過程中加載 SQL 數據。

例如,spring boot 與 Flyway 的集成就是這樣工作的(Flyway 的 bean 被創建和加載)。 因此,理論上,您可以僅將 Flyway 與包含測試數據生成的所有相關 SQL 腳本的測試遷移一起使用。

你怎么能在技術上做到這一點?

這是一種方法:

創建一個特殊的 bean(就像它與 Flyway 的工作方式一樣),它取決於您的存儲庫並在后期構造中保存數據:

@Component
public class SqlGenerationBean {

   @Autowired
   private MyRepository repo;

   @PostConstruct
   public void init() {
      repo.save();
   } 
}

另一種做法是創建一個偵聽器,該偵聽器將在應用程序上下文啟動時調用,並再次調用相同的repo.save()

在這兩種情況下,bean/偵聽器代碼不應該從生產中訪問(它僅用於測試):因此將它放在src/test/java下的某個位置,例如

現在一旦應用程序上下文啟動,您就可以使用一個巧妙的技巧:

使用@Transactional注釋標記您的測試。 Spring 會將代碼包裝在一個人工事務中,該事務將自動回滾(即使測試成功),以便您在測試期間修改的所有數據都將回滾,並且基本上在每次測試之前,您將擁有相同的狀態(即與應用程序上下文啟動時/之后的數據庫狀態相同)。 當然,如果在測試中使用DDL,有些數據庫不能將其作為事務的一部分,但它確實取決於數據庫。

這里另一個有趣的點是,即使在測試用例之間(僅創建一次),應用程序上下文也可以緩存,因此請記住這一點。

在這種情況下,我只會為測試類創建一個構造函數。 它會在一切發生之前被觸發。

@BeforeEach 在每次測試之前運行,但在所有初始化之后運行。

您也可以只使用 Mockito 並模擬結果,而無需清理和過度復雜化

暫無
暫無

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

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