1

我编写了这个测试来验证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
    }
}

测试日志(缩短):

INFO 13522 --- [           main] o.s.t.c.transaction.TransactionContext   : Began transaction (1) for test context [DefaultTestContext@8f8717b testClass = DomainRepositoryTest,...]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@65f36591]; rollback [true]

Hibernate: insert into domains (name, id) values (?, ?)
Hibernate: insert into domains (name, id) values (?, ?)
Hibernate: insert into domains (name, id) values (?, ?)

INFO 13522 --- [           main] o.s.t.c.transaction.TransactionContext   : Rolled back transaction for test: [DefaultTestContext@8f8717b testClass = DomainRepositoryTest, ...], attributes = map[[empty]]]

问题:如何解决这个测试?附加问题:为什么在日志中有 3 个插入操作?

数据库:H2

4

2 回答 2

0

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

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

  1. 添加 liquibase-core jar 以测试类路径并将其配置为运行迁移
  2. 在域实体上声明@UniqueConstraint并依赖 Hibernate DDL。
于 2019-05-05T14:36:02.410 回答
-1

The reason is that saveAndFlash() is doing an update to the entity if it exists (Yes, the name of the method is confusing..)

If you want to check your case, you need to override saveAndFlash() and use EntityManager by using persist method. Here an example of override save() method of Spring JPA:

@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);
    }
}
于 2019-05-05T12:55:34.313 回答