问题描述
@Entity
class Employee {
@Column(name = "first_name",length = 14)
private String firstName;
@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();
但是再次,这也不正确。..如何在没有任何解决方法或其他语句的情况下使该测试失败?
解决方法
这种情况下最简单的选择是配置@Transactional
批注,强制将测试中的所有更改发送给数据库(只能在特定的测试中使用):
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。
您可以在下图中看到结果:
,您可以使用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()
方法。