SpringBoot中@DataJpaTest 和 JUnit 中的儲存庫類

banq發表於2024-02-29

當使用使用Spring Data JPA進行資料持久化的 Spring Boot 應用程式時,測試與資料庫互動的儲存庫至關重要。在本教程中,我們將探索如何使用Spring Boot 和JUnit提供的@DataJpaTest註釋來有效地測試 Spring Data JPA 儲存庫。

@DataJpaTest是什麼?
@DataJpaTest  註解用於測試 Spring Boot 應用程式中的 JPA 儲存庫。它是一個專門的測試註釋,為測試持久層提供了最小的 Spring 上下文。此註釋可以與其他測試註釋(例如@RunWith 和 @SpringBootTest )結合使用 。

此外,@DataJpaTest的範圍僅限於應用程式的 JPA 儲存庫層。它不會載入整個應用程式上下文,這可以使測試更快、更集中。 此註釋還提供了用於測試 JPA 實體的預配置EntityManager 和 TestEntityManager 。

儲存庫Repository 類
在 Spring Data JPA 中,儲存庫充當 JPA 實體之上的抽象層。它提供了一組用於執行 CRUD(建立、讀取、更新、刪除)操作和執行自定義查詢的方法。這些儲存庫通常從JpaRepository等介面擴充套件,負責處理與特定實體型別相關的資料庫互動。

@DataJpaTest引數
@DataJpaTest確實有一些可選引數,我們可以使用它們來自定義測試環境。

1. 特性
此引數允許我們指定將應用於我們的測試上下文的 Spring Boot 配置屬性。這對於調整資料庫連線詳細資訊、事務行為或與我們的測試需求相關的其他應用程式屬性等設定很有用:

@DataJpaTest(properties = {
    <font>"spring.datasource.url=jdbc:h2:mem:testdb",
   
"spring.jpa.hibernate.ddl-auto=create-drop"
})
public class UserRepositoryTest {
   
// ... test methods<i>
}

2. 顯示Sql
這為我們的測試啟用了 SQL 日誌記錄,並允許我們檢視儲存庫方法執行的實際 SQL 查詢。此外,這可以幫助除錯或理解 JPA 查詢是如何轉換的。預設情況下,SQL 日誌記錄處於啟用狀態。我們可以透過將值設定為false來關閉它:

@DataJpaTest(showSql = false)
public class UserRepositoryTest {
    <font>// ... test methods<i>
}

3. 包含過濾器和排除過濾器
這些引數使我們能夠在元件掃描期間包含或排除特定元件。我們可以使用它們來縮小掃描範圍並透過僅關注相關元件來最佳化測試效能:

@DataJpaTest(includeFilters = @ComponentScan.Filter(
    type = FilterType.ASSIGNABLE_TYPE, 
    classes = UserRepository.class),
  excludeFilters = @ComponentScan.Filter(
    type = FilterType.ASSIGNABLE_TYPE, 
    classes = SomeIrrelevantRepository.class))
public class UserRepositoryTest {
    <font>// ... test methods<i>
}

主要特點

  • 測試環境配置:為 JPA 儲存庫設定適當的測試環境可能既耗時又棘手。@DataJpaTest提供了一個現成的測試環境,其中包括用於測試 JPA 儲存庫的基本元件,例如EntityManager和DataSource。該環境是專門為測試 JPA 儲存庫而設計的。它確保我們的儲存庫方法在測試事務的上下文中執行,與安全的記憶體資料庫(如 H2)而不是生產資料庫進行互動。
  • 依賴注入:@DataJpaTest簡化了我們的測試類中的依賴注入過程。儲存庫以及其他重要的 bean 會自動注入到測試上下文中。這種無縫整合使開發人員能夠專注於編寫簡潔有效的測試用例,而無需進行顯式 bean 連線的麻煩。
  • 預設回滾:此外,保持測試的獨立性和可靠性至關重要。預設情況下,每個用@DataJpaTest註釋的測試方法在事務邊界內執行。這可確保對資料庫所做的更改在測試結束時自動回滾,為下一次測試留下乾淨的記錄。

配置和設定
要使用@DataJpaTest,我們需要將spring-boot-starter-test 依賴項新增到範圍為“ test ”的專案中。這種輕量級依賴項包括用於測試的 JUnit 等基本測試庫,確保它不包含在我們的生產構建中。

將以下依賴項新增到pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-test</artifactId>
    <scope>test</scope>
</dependency>

新增依賴項後,我們可以在測試中使用@DataJpaTest註釋。該註釋設定了一個記憶體中的 H2 資料庫併為我們配置 Spring Data JPA,允許我們編寫與儲存庫類互動的測試。

建立實體類
現在,讓我們建立User實體類,它將表示使用者資料:

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;
    private String password;
    
    <font>// getters and setters<i>
}

建立儲存庫介面
接下來,我們定義UserRepository,一個用於管理User實體的 Spring Data JPA 儲存庫介面:

public interface UserRepository extends JpaRepository<User, Long> {
    <font>// Add custom methods if needed<i>
}

透過擴充套件JpaRepository<User, Long>,我們的UserRepository可以訪問 Spring Data JPA 開箱即用提供的標準 CRUD 操作。

此外,我們可以在此介面中定義自定義查詢方法來滿足特定的資料訪問檢索需求,例如findByUsername():

public interface UserRepository extends JpaRepository<User, Long> {
    <font>// Custom query method to find a user by username<i>
    User findByUsername(String username);


實施儲存庫測試
為了測試應用程式的儲存庫層,我們將利用@DataJpaTest註釋。透過使用這個註解,將建立一個記憶體H2資料庫,並配置Spring Data JPA。這允許我們編寫與儲存庫類互動的測試。

1、設定測試類
首先,讓我們透過使用@DataJpaTest註釋來設定測試類。此註釋掃描使用@Entity和 Spring Data JPA 儲存庫介面註釋的實體類。這可確保僅載入相關元件進行測試,從而提高測試重點和​​效能:

@DataJpaTest
public class UserRepositoryTest {
    <font>// Add test methods here<i>
}

要建立儲存庫測試用例,我們首先需要將要測試的儲存庫注入到測試類中。這可以使用@Autowired註釋來完成 :

@Autowired
private UserRepository userRepository;

2、測試生命週期管理
在測試生命週期管理的上下文中,@BeforeEach和@AfterEach註釋分別用於在每個測試方法之前和之後執行設定和拆卸操作。這確保了每個測試方法在乾淨且隔離的環境中執行,具有一致的初始條件和清理程式。

以下是我們如何將測試生命週期管理合併到我們的測試類中:

@BeforeEach
public void setUp() {
    <font>// 在每個測試方法之前初始化測試資料<i>
    testUser = new User();
    testUser.setUsername(
"testuser");
    testUser.setPassword(
"password");
    userRepository.save(testUser);
}
@AfterEach
public void tearDown() {
   
// 在每種測試方法之後釋出測試資料<i>
    userRepository.delete(testUser);
}

在使用@BeforeEach註解的setUp()方法中,我們可以在每個測試方法執行之前執行所需的任何必要的設定操作。這可能包括初始化測試資料、設定模擬物件或準備測試所需的資源。

相反,在用@AfterEach註釋的tearDown()方法中,我們可以在每個測試方法執行後執行清理操作。這可能涉及重置測試期間所做的任何更改、釋放資源或執行任何必要的清理任務以將測試環境恢復到其原始狀態。

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方法正在按預期執行。

4. 測試更新操作
另外,我們可以建立一個測試用例來測試更新操作:

@Test
void givenUser_whenUpdated_thenCanBeFoundByIdWithUpdatedData() {
    testUser.setUsername(<font>"updatedUsername");
    userRepository.save(testUser);
    User updatedUser = userRepository.findById(testUser.getId()).orElse(null);
    assertNotNull(updatedUser);
    assertEquals(
"updatedUsername", updatedUser.getUsername());
}

5. 測試findByUsername()方法
現在,讓我們測試我們建立的findByUsername()自定義查詢方法:

@Test
void givenUser_whenFindByUsernameCalled_thenUserIsFound() {
    User foundUser = userRepository.findByUsername(<font>"testuser");
    assertNotNull(foundUser);
    assertEquals(
"testuser", foundUser.getUsername());
}

事務行為
預設情況下,所有用@DataJpaTest註釋的測試都在事務中執行。這意味著測試期間對資料庫所做的任何更改都會在測試結束時回滾,以確保資料庫保持其原始狀態。此預設行為透過防止測試之間的干擾和資料損壞來簡化測試。

但是,在某些情況下,我們可能需要禁用事務行為來測試某些場景。例如,測試結果可能需要在測試之外持續存在。

在這種情況下,我們可以使用@Transactional註釋和propagation= propagation.NOT_SUPPORTED禁用特定測試類的事務:

@DataJpaTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public class UserRepositoryIntegrationTest {
    <font>// ... test methods<i>
}

或者我們可以禁用單個測試方法的事務:

@Test
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void testMyMethodWithoutTransactions() {
    <font>// ... code that modifies the database<i>


結論
在本文中,我們學習瞭如何使用@DataJpaTest來測試JUnit中的 JPA 儲存庫。總的來說,@DataJpaTest是一個強大的註釋,用於在 Spring Boot 應用程式中測試 JPA 儲存庫。它提供了一個集中的測試環境和用於測試持久層的預配置工具。透過使用@DataJpaTest,我們可以確保我們的 JPA 儲存庫正常執行,而無需啟動整個 Spring 上下文。

 

相關文章