Kotlin 在@DataJpaTest中测试唯一约束

Kotlin 在@DataJpaTest中测试唯一约束,kotlin,spring-data-jpa,unique-constraint,database-testing,Kotlin,Spring Data Jpa,Unique Constraint,Database Testing,我编写此测试是为了验证数据库中Domain.name上的唯一约束。但它不起作用:我希望在domainRepository.saveAndFlush(domainDuplicate)操作中抛出异常,但测试成功结束 @RunWith(SpringRunner::class) @DataJpaTest class DomainRepositoryTest { @Autowired private lateinit var util: TestEntityManager @Au

我编写此测试是为了验证数据库中
Domain.name
上的唯一约束。但它不起作用:我希望在
domainRepository.saveAndFlush(domainDuplicate)
操作中抛出异常,但测试成功结束

@RunWith(SpringRunner::class)
@DataJpaTest
class DomainRepositoryTest {

    @Autowired
    private lateinit var util: TestEntityManager
    @Autowired
    private lateinit var domainRepository: DomainRepository

    @Test
    fun testNonUniqueDomainSave() {
        // Arrange
        val domain = Domain(name = "name")
        util.persist(domain)
        util.flush()
        util.clear()

        val domainDuplicate = domain.copy(id = 0L)

        // Act
        domainRepository.saveAndFlush(domainDuplicate)
        // Exception is expected
    }
}
测试日志(缩短):

问题:如何修复此测试? 附加问题:为什么在日志中插入3个操作


数据库:H2

原因是
saveAndFlash()
正在对实体进行更新(如果实体存在)(是的,方法的名称令人困惑..)

如果要检查案例,需要重写
saveAndFlash()
,并使用
persist
方法使用
EntityManager
。 下面是Spring JPA的override
save()
方法的一个示例:

@PersistenceContext
private EntityManager em;

@Override
@Transactional
public Domain save(Domain domain) {

    if (domain.getId() == null) {
       em.persist(domain);
       return domain;
    } else {
      return em.merge(domain);
    }
}

这是测试中数据库初始化的一个问题:没有唯一的约束!我假设Liquibase应该在任何测试之前运行迁移,但事实上,它并没有配置为这样做。默认情况下,Hibernate DDL自动更新用于在测试中创建DB模式

我可以想出两种可能的解决方案:

  • 将liquibase core jar添加到测试类路径,并将其配置为运行迁移
  • 在域实体上声明
    @UniqueConstraint
    ,并依赖Hibernate DDL

  • 这很可能是因为我的实体从未写入数据库。。。如何触发写入?请发布您的
    @PersistenceContext
    private EntityManager em;
    
    @Override
    @Transactional
    public Domain save(Domain domain) {
    
        if (domain.getId() == null) {
           em.persist(domain);
           return domain;
        } else {
          return em.merge(domain);
        }
    }