I am having trouble testing the auditing annotations in Spring JPA (2.5.4) using an H2 in-memory database. I have a main class annotated with @EnableJpaAuditing
, and a base class for my entities.
@Getter
@Setter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class AuditedEntity {
@CreatedDate
LocalDateTime createdDate;
@LastModifiedDate
LocalDateTime lastModifiedDate;
}
Two entities extend the base class: a parent and a child.
@Data
@Entity
@Table(name = "one2many")
class OneToManyEntity extends AuditedEntity {
@Id
@GeneratedValue(strategy = SEQUENCE)
Integer id;
@OneToMany(mappedBy = "parent", cascade = ALL, orphanRemoval = true)
List<ManyToOneEntity> children;
}
@Data
@Entity
@Table(name = "many2one")
class ManyToOneEntity extends AuditedEntity {
@Id
@GeneratedValue(strategy = SEQUENCE)
Integer id;
@ManyToOne(optional = false, fetch = LAZY)
OneToManyEntity parent;
}
The repository for the parent entity is a simple interface declaration.
@Repository
interface OneToManyRepository extends CrudRepository<OneToManyEntity, Integer> {
}
And I have a couple of Spock tests for it.
class OneToManyRepoSpec extends Specification {
@Autowired
OneToManyRepository repo
def "test ID is assigned"() {
given:
def parent = new OneToManyEntity()
parent.setChildren([new ManyToOneEntity()])
expect:
def persisted = repo.save(parent)
persisted.getId() > 0
persisted.getLastModifiedDate() != null
}
def "LastModifiedDate value is updated"() {
given:
def persisted1 = repo.save(new OneToManyEntity())
sleep(1000)
persisted1.setChildren([])
def persisted2 = repo.save(persisted1)
expect:
persisted2.lastModifiedDate.isAfter(persisted1.lastModifiedDate)
}
}
I can get either of these tests to pass, depending on how I annotate the test class; but I cannot get both tests to pass together.
- If I annotate the test class with
@DataJpaTest
the first test passes (IDs and audit values are assigned) but the second test fails (audit values are not updated). - If I annotate the test class with
@SpringBootTest(webEnvironment = NONE)
the first test fails (ConstraintViolationException: NULL not allowed for column "parent_id";
so IDs are not assigned) but the second test passes (audit values are updated).
Do I have to split these tests into different classes with different annotations, or is there a way to keep them together and both passing? I'd also be interested to understand more about what causes these separate test failures.