![](/img/trans.png)
[英]Spring Boot Application is throwing exception when runs from Junit 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.