在測試運行時,測試類中 @Transactional
註解,會致使測試中 Entity
數據的操做都是在內存中完成,最終並不會進行 commit
操做,也就是不會將 Entity
數據進行持久化操做,從而致使測試的行爲和真實應用的行爲不一致。html
事務管理在應用開發中是種不可或缺的設計,它是數據庫持久化處理的一種標準。咱們知道,應用程序開發離不開對數據的CRUD
(增刪改查),事務的ACID
性能夠更好保證數據的完整性,保證相關數據的同生共死
。單個事務生命週期主要分爲三個階段,BEGIN TRANSACTION
-> COMMIT TRANSACTION
-> ROLLBACK TRANSACTION
。java
Spring Boot
事務的使用分爲命令式和聲明式經常使用的方式是聲明式註解(@Transactional
)。事務管理既能夠在應用層使用,也能夠在測試中使用。git
爲了保證測試之間的相互獨立,測試之間數據不會被相互影響。也許你寫過這樣的測試:github
@SpringBootTest @ActiveProfiles("test") @Transactional public class UserControllerTest { }
@Transactional
經過將數據持久化操做截斷,來解決測試之間相互對立,數據相互不影響的問題。然而這樣方式會有反作用,就是數據持久化的過程再也不真實,沒有了commit
的過程。從而會致使:spring
- 沒法保證
Entity
之間關聯關係,惟一索引和主外鍵關聯的準確性- 沒法保證
Entity
建立時間、更新時間和版本化(樂觀鎖)的賦值邏輯的準確性- 沒法保證
Entity
中有@Transient
註解的屬性的賦值邏輯的準確性- 測試的數據不是真實場景存在的問題
- 測試中,單個事務中的準備數據,沒法在多線程中共享。
......數據庫
而後 Spring
在測試問題域中引入事務管理初衷是什麼?爲了解決什麼問題才須要將它引入?官方文檔介紹 Transaction management多線程
按照官方文檔意思,爲了解決測試運行時,程序訪問真實的數據庫,改變數據的狀態,從而影響到後續的測試問題。測試
其實這裏應該批判性思惟一下,爲何測試運行時,須要訪問真實的數據庫?爲何測試之間的數據會相互影響?
對於每一個測試來講,每次運行前都應該有乾淨的上下文,或者說獨立的上下文,有數據清理和準備的過程,測試與測試之間相互隔離。也就是說,爲何測試不能用內存數據庫或者嵌入式數據庫?爲何不是每一個測試運行前清理一下數據庫中的數據,保證測試用例運行前的一方淨土,不被上個測試數據影響?spa
答案固然是,能夠!!!線程
如何作?實現一個 TruncateDatabaseService
,只刪除表的數據,不刪除表的結果。 在測試基類的@BeforeEach
,執行 truncate
。源碼Truncate Database:
TruncateDatabaseBasicOnHibernateService
TruncateDatabaseBasicOnMybatisService
原文連接