spring-data-jpa 如何使DataJpaTest自动刷新保存?

v1uwarro  于 2022-11-10  发布在  Spring
关注(0)|答案(2)|浏览(165)

我有一个Employee实体,其中包含以下列:

@Entity
class Employee {
  @Column(name = "first_name", length = 14)
  private String firstName;

我有一个Spring JPA存储库:

@Repository
public interface EmployeeRepository extends CrudRepository<Employee, Integer> {

test/resources/application.properties中,我有以下内容,因此我使用了内存中的h2数据库,其中的表是自动生成的:

spring.jpa.hibernate.ddl-auto=create
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa

我预计这个测试会失败,因为firstName比允许的长度长:

@DataJpaTest
public class EmployeeRepositoryTest {

  @Autowired
  private EmployeeRepository employeeRepository;

  @Test
  public void mustNotSaveFirstNameLongerThan14() {
    Employee employee = new Employee();
    employee.setFirstName("koraykoraykoray");  // 15 characters!
    employeeRepository.save(employee);
  }
}

我很惊讶地看到这个测试没有失败,但是下面的测试失败了:

@DataJpaTest
public class EmployeeRepositoryTest {

  @Autowired
  private EmployeeRepository employeeRepository;

  @Test
  public void testMustNotSaveFirstNameLongerThan14() {
    Employee employee = new Employee();
    employee.setFirstName("koraykoraykoray");  // 15 characters!
    employeeRepository.save(employee);
    employeeRepository.findAll();
  }
}

使用堆栈跟踪:

Caused by: org.h2.jdbc.JdbcSQLDataException: Value too long for column "FIRST_NAME VARCHAR(14)": "'koraykoraykoray' (15)"; SQL statement:

唯一的区别是第二个测试有额外的employeeRepository.findAll();语句,据我所知,该语句强制Hibernate刷新。
这对我来说感觉不对,我更希望save的测试立即失败。
我也可以有

@Autowired
private TestEntityManager testEntityManager;

以及呼叫了

testEntityManager.flush();

但是,这也不 * 感觉 * 正确。我如何在没有任何变通方法或附加语句的情况下使这个测试失败?

ttygqcqt

ttygqcqt1#

在您的情况下,最简单的选项是配置@Transactional注解,强制向数据库发送您测试中的所有更改(它只能在特定的测试中使用):

import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import static org.junit.jupiter.api.Assertions.assertThrows;

@Transactional(propagation = Propagation.NOT_SUPPORTED)
@DataJpaTest
public class EmployeeRepositoryTest {

  @Autowired
  private EmployeeRepository employeeRepository;

  @Test
  public void mustNotSaveFirstNameLongerThan14() {
    Employee employee = new Employee();
    employee.setId(1);
    employee.setFirstName("koraykoraykoray");  // 15 characters!
    assertThrows(DataIntegrityViolationException.class, () -> {
        employeeRepository.save(employee);
    });
  }

  @Test
  public void mustSaveFirstNameShorterThan14() {
    Employee employee = new Employee();
    employee.setId(1);
    employee.setFirstName("koraykor");  // 8 characters!
    employeeRepository.save(employee);
  }
}

**PD:**由于您的存储库定义,我添加了一个简单的Integer属性作为Employee实体的PK。

您可以在下图中看到结果:

wribegjk

wribegjk2#

您可以使用JpaRepository<T,ID>来代替CrudRepository<T,ID>。例如:

@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Integer>

然后,您可以在任何需要立即发送数据的地方使用它的saveAndFlush()方法:

@Test
public void mustNotSaveFirstNameLongerThan14() {
  Employee employee = new Employee();
  employee.setFirstName("koraykoraykoray");  // 15 characters!
  employeeRepository.saveAndFlush(employee);
}

在您希望优化的代码中,您仍然可以使用save()方法。

相关问题