網頁

2021/5/5

Spring Boot Test 整合測試資料庫存取交易回滾 integration test database access transaction rollback

Spring Boot Test 進行資料存取測試時,測試結束後回滾資料異動的方式如下。

以Spring Data JPA的Repository為例,此類為存取資料庫的介面,例如EmployeeRepository,而其測試類為EmployeeRepositoryTests

EmployeeRepositoryTests測試類別或方法前掛上@Transactional則該類別或方法對資料庫進行的異動在測試結束後會回滾。

例如下面在測試類前掛上@Transactional,則此類中所有的測試方法對資料庫的異動皆會回滾。

EmployeeRepositoryTests

@Transactional // 此測試類下的方法都會回滾
@SpringBootTest
public class EmployeeRepositoryTests {

    @Autowired
    private EmployeeRepository employeeRepository;

    @Test
    public void save() {
        
        Employee employee = new Employee();
        employee.setId(1);
        employee.setName("john");
        
        employee = employeeRepository.save(employee);
        
        Assertions.assertEquals(1, employee.getId());
    }

}

@Transactional掛在測試方法上,則只有該方法才會回滾。

EmployeeRepositoryTests

@SpringBootTest
public class EmployeeRepositoryTests {

    @Autowired
    private EmployeeRepository employeeRepository;

    @Transactional // 此測試方法會回滾
    @Test
    public void save() {
        
        Employee employee = new Employee();
        employee.setId(1);
        employee.setName("john");
        
        employee = employeeRepository.save(employee);
        
        Assertions.assertEquals(1, employee.getId());
    }

}

如果測試類或方法沒加上@Transactional則不會回滾。之前我誤以為測試類對資料庫的交易會自動回滾,但其實不會,必須加上@Transactional才會回滾。


若類別@Transactional又希望特定方法不要回滾,則在方法前加上@Rollback(false)

EmployeeRepositoryTests

@Transactional
@SpringBootTest
public class EmployeeRepositoryTests {

    @Autowired
    private EmployeeRepository employeeRepository;

    @Rollback(false) // 此測試方法不會回滾
    @Test
    public void save() {
        
        Employee employee = new Employee();
        employee.setId(1);
        employee.setName("john");

        employee = employeeRepository.save(employee);
        
        Assertions.assertEquals(1, employee.getId());
    }

}

@Rollback(false)也可用@Commit替代,兩者效果相同,都是測試結束後不回滾。

EmployeeRepositoryTests

@Transactional
@SpringBootTest
public class EmployeeRepositoryTests {

    @Autowired
    private EmployeeRepository employeeRepository;

    @Commit // 效果同@Rollback(false),不回滾
    @Test
    public void save() {
        
        Employee employee = new Employee();
        employee.setId(1);
        employee.setName("john");
        
        employee = employeeRepository.save(employee);
        
        Assertions.assertEquals(1, employee.getId());
    }

}

@Rollback(false)@Commit也都可以放在類別前,則整個類別的交易不回滾。

EmployeeRepositoryTests

@Commit // 效果同@Rollback(false),此測試類下的方法都不回滾
@Transactional
@SpringBootTest
public class EmployeeRepositoryTests {

    @Autowired
    private EmployeeRepository employeeRepository;

    @Test
    public void save() {
        
        Employee employee = new Employee();
        employee.setId(1);
        employee.setName("john");
        
        employee = employeeRepository.save(employee);
        
        Assertions.assertEquals(1, employee.getId());
    }

}

不要在同個類別或方法混用@Rollback(false)@Commit否則結果無法預期。


沒有留言:

張貼留言