2

I wrote this test to verify unique constraint on Domain.name in the database. But it doesn't work: I expect an exception to be thrown on the domainRepository.saveAndFlush(domainDuplicate) operation, but the test ends successfully.

@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
    }
}

Test log (shortened):

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]]]

Question: How to fix this test? Additional question: Why 3 insert operations in log?

Database: H2

naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259

2 Answers2

0

It was a problem with database initialization in tests: there was no unique constraint! I assumed that Liquibase should run migrations before any tests but in fact, it was not configured to do so. By default, Hibernate DDL auto update is used to create DB schema in tests.

I can think of 2 possible solutions:

  1. add liquibase-core jar to test classpath and configure it to run migrations
  2. declare @UniqueConstraint on domain entity and rely on Hibernate DDL.
naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
-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);
    }
}
Gal Naor
  • 2,397
  • 14
  • 17