JUnit 中的 @DataJpaTest 和儲存庫類
一、簡介
當使用使用 Spring Data JPA 進行資料持久化的 Spring Boot 應用程式時,測試與資料庫互動的儲存庫至關重要。在本教程中,我們將探索如何使用 Spring Boot 和 JUnit 提供的@DataJpaTest
註解來有效測試 Spring Data JPA 儲存庫。
2.了解@DataJpaTest
和Repository類
在本節中,我們將深入研究 Spring Boot 應用程式上下文中@DataJpaTest
和類別儲存庫之間的交互作用。
2.1. @DataJpaTest
@DataJpaTest
註解用於測試 Spring Boot 應用程式中的 JPA 儲存庫。它是一個專門的測試註釋,為測試持久層提供了最小的 Spring 上下文。此註解可以與其他測試註解(例如@RunWith
和@SpringBootTest
結合使用。
此外, @DataJpaTest
的範圍僅限於應用程式的 JPA 儲存庫層。它不會載入整個應用程式上下文,這可以使測試更快、更集中。此註解也提供了用於測試 JPA 實體的預先配置EntityManager
和TestEntityManager
。
2.2.儲存庫類
在 Spring Data JPA 中,儲存庫充當 JPA 實體之上的抽象層。它提供了一組用於執行 CRUD(建立、讀取、更新、刪除)操作和執行自訂查詢的方法。這些儲存庫通常從JpaRepository
等介面擴展,負責處理與特定實體類型相關的資料庫互動。
3.可選參數
@DataJpaTest
確實有一些可選參數,我們可以使用它們來自訂測試環境。
3.1. properties
此參數允許我們指定將應用於我們的測試上下文的 Spring Boot 配置屬性。這對於調整資料庫連接詳細資訊、事務行為或與我們的測試需求相關的其他應用程式屬性等設定很有用:
@DataJpaTest(properties = {
"spring.datasource.url=jdbc:h2:mem:testdb",
"spring.jpa.hibernate.ddl-auto=create-drop"
})
public class UserRepositoryTest {
// ... test methods
}
3.2. showSql
這為我們的測試啟用了 SQL 日誌記錄,並允許我們查看儲存庫方法執行的實際 SQL 查詢。此外,這可以幫助調試或理解 JPA 查詢是如何轉換的。預設情況下,SQL 日誌記錄處於啟用狀態。我們可以透過將值設為false
來關閉它:
@DataJpaTest(showSql = false)
public class UserRepositoryTest {
// ... test methods
}
3.3. includeFilters
和excludeFilters
這些參數使我們能夠在組件掃描期間包含或排除特定組件。我們可以使用它們來縮小掃描範圍並透過僅關注相關組件來優化測試效能:
@DataJpaTest(includeFilters = @ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
classes = UserRepository.class),
excludeFilters = @ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
classes = SomeIrrelevantRepository.class))
public class UserRepositoryTest {
// ... test methods
}
4. 主要特點
當在 Spring Boot 應用程式中測試 JPA 儲存庫時, @DataJpaTest
註解可能是一個方便的工具。讓我們詳細探討其主要功能和優勢。
4.1.測試環境配置
為 JPA 儲存庫設定適當的測試環境可能既耗時又棘手。 @DataJpaTest
提供了一個現成的測試環境,其中包括用於測試 JPA 儲存庫的基本元件,例如EntityManager
和DataSource
。
該環境是專門為測試 JPA 儲存庫而設計的。它確保我們的儲存庫方法在測試事務的上下文中運行,與安全的記憶體資料庫(如 H2)而不是生產資料庫進行互動。
4.2.依賴注入
@DataJpaTest
簡化了我們的測試類別中的依賴注入過程。儲存庫以及其他重要的 bean 會自動注入測試上下文。這種無縫整合使開發人員能夠專注於編寫簡潔有效的測試案例,而無需進行明確 bean 連接的麻煩。
4.3.預設回滾
此外,保持測試的獨立性和可靠性至關重要。預設情況下,每個用@DataJpaTest
註解的測試方法在事務邊界內運行。這可確保對資料庫所做的變更在測試結束時自動回滾,為下一次測試留下乾淨的記錄。
5. 配置和設定
要使用@DataJpaTest
,我們需要將spring-boot-starter-test
依賴項新增到範圍為「 test
」的專案中。這種輕量級依賴項包括用於測試的 JUnit 等基本測試庫,確保它不包含在我們的生產建置中。
5.1.新增依賴到pom.xml
讓我們將以下依賴項新增至pom.xml
:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-test</artifactId>
<scope>test</scope>
</dependency>
新增依賴項後,我們可以在測試中使用@DataJpaTest
註解。此註解設定了一個記憶體中的 H2 資料庫並為我們配置 Spring Data JPA,讓我們可以編寫與儲存庫類別互動的測試。
5.2.建立實體類別
現在,讓我們建立User
實體類,它將表示使用者資料:
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
// getters and setters
}
5.3.建立儲存庫介面
接下來,我們定義UserRepository
,一個用於管理User
實體的 Spring Data JPA 儲存庫介面:
public interface UserRepository extends JpaRepository<User, Long> {
// Add custom methods if needed
}
透過擴充JpaRepository<User, Long>
,我們的UserRepository
可以存取 Spring Data JPA 開箱即用提供的標準 CRUD 操作。
此外,我們可以在此介面中定義自訂查詢方法來滿足特定的資料存取擷取需求,例如findByUsername()
:
public interface UserRepository extends JpaRepository<User, Long> {
// Custom query method to find a user by username
User findByUsername(String username);
}
6. 實施儲存庫測試
為了測試應用程式的儲存庫層,我們將利用@DataJpaTest
註解。透過使用這個註解,將建立一個記憶體H2資料庫,並配置Spring Data JPA。這允許我們編寫與儲存庫類別互動的測試。
6.1.設定測試類
首先,讓我們透過使用@DataJpaTest
註解來設定測試類別。此註解掃描使用@Entity
和 Spring Data JPA 儲存庫介面註解的實體類別。這可確保僅載入相關元件進行測試,從而提高測試重點和效能:
@DataJpaTest
public class UserRepositoryTest {
// Add test methods here
}
要建立儲存庫測試案例,我們首先需要將要測試的儲存庫注入到測試類別中。這可以使用@Autowired
註解來完成:
@Autowired
private UserRepository userRepository;
6.2.測試生命週期管理
在測試生命週期管理的上下文中, @BeforeEach
和@AfterEach
註釋分別用於在每個測試方法之前和之後執行設定和拆卸操作。這確保了每個測試方法在乾淨且隔離的環境中運行,具有一致的初始條件和清理程序。
以下是我們如何將測試生命週期管理合併到我們的測試類別中:
@BeforeEach
public void setUp() {
// Initialize test data before each test method
testUser = new User();
testUser.setUsername("testuser");
testUser.setPassword("password");
userRepository.save(testUser);
}
@AfterEach
public void tearDown() {
// Release test data after each test method
userRepository.delete(testUser);
}
在使用@BeforeEach
註解的setUp()
方法中,我們可以在每個測試方法執行之前執行所需的任何必要的設定操作。這可能包括初始化測試資料、設定模擬物件或準備測試所需的資源。
相反,在用@AfterEach
註釋的tearDown()
方法中,我們可以在每個測試方法執行後執行清理操作。這可能涉及重置測試期間所做的任何更改、釋放資源或執行任何必要的清理任務以將測試環境恢復到原始狀態。
6.3.測試插入操作
現在,我們可以編寫與 JPA 儲存庫互動的測試方法。例如,我們可能想要測試是否可以將新使用者儲存到資料庫中。由於在每次測試之前都會自動保存用戶,因此我們可以直接專注於測試與 JPA 儲存庫的互動:
@Test
void givenUser_whenSaved_thenCanBeFoundById() {
User savedUser = userRepository.findById(testUser.getId()).orElse(null);
assertNotNull(savedUser);
assertEquals(testUser.getUsername(), savedUser.getUsername());
assertEquals(testUser.getPassword(), savedUser.getPassword());
}
如果我們觀察測試案例的控制台日誌,我們會注意到以下日誌:
Began transaction (1) for test context
.....
Rolled back transaction for test:
這些日誌表明@BeforeEach
和@AfterEach
方法正在按預期運行。
6.4.測試更新操作
另外,我們可以建立一個測試案例來測試更新操作:
@Test
void givenUser_whenUpdated_thenCanBeFoundByIdWithUpdatedData() {
testUser.setUsername("updatedUsername");
userRepository.save(testUser);
User updatedUser = userRepository.findById(testUser.getId()).orElse(null);
assertNotNull(updatedUser);
assertEquals("updatedUsername", updatedUser.getUsername());
}
6.5.測試findByUsername()
方法
現在,讓我們測試我們建立的findByUsername()
自訂查詢方法:
@Test
void givenUser_whenFindByUsernameCalled_thenUserIsFound() {
User foundUser = userRepository.findByUsername("testuser");
assertNotNull(foundUser);
assertEquals("testuser", foundUser.getUsername());
}
7. 交易行為
預設情況下,所有用@DataJpaTest
註解的測試都在事務中執行。這意味著測試期間對資料庫所做的任何更改都會在測試結束時回滾,以確保資料庫保持其原始狀態。此預設行為透過防止測試之間的干擾和資料損壞來簡化測試。
但是,在某些情況下,我們可能需要停用事務行為來測試某些場景。例如,測試結果可能需要在測試之外持續存在。
在這種情況下,我們可以使用@Transactional
註解和propagation = propagation.NOT_SUPPORTED
來停用特定測試類別的事務:
@DataJpaTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public class UserRepositoryIntegrationTest {
// ... test methods
}
或者我們可以禁用單一測試方法的事務:
@Test
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void testMyMethodWithoutTransactions() {
// ... code that modifies the database
}
八、結論
在本文中,我們學習如何使用@DataJpaTest
來測試JUnit
中的 JPA 儲存庫。總的來說, @DataJpaTest
是一個強大的註釋,用於在 Spring Boot 應用程式中測試 JPA 儲存庫。它提供了一個集中的測試環境和用於測試持久層的預先配置工具。透過使用@DataJpaTest
,我們可以確保我們的 JPA 儲存庫正常運行,而無需啟動整個 Spring 上下文。
與往常一樣,範例的原始程式碼可在 GitHub 上取得。