I want to write integration tests for my RestAPI endpoints, and I'm struggling with @EnableJpaAuditing. I want some of my entities to be audited by Spring, so I've created the following configuration class:
@Configuration
@EnableJpaAuditing
public class PersistenceAuditConfiguration {
}
Which I import into my main application config:
@ServletComponentScan
@SpringBootApplication
@Import(PersistenceAuditConfiguration.class)
public class TMTWebApplication {
public static void main(String[] args) {
SpringApplication.run(TMTWebApplication.class, args);
}
}
Also, I have an abstract base class for all entities that I want to be audited:
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@JsonIgnoreProperties(value = {"createdAt", "updatedAt"}, allowGetters = true)
public abstract class AuditableEntity extends EpicPojo implements Serializable {
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created_at", nullable = false, updatable = false)
@CreatedDate
private Date createdAt;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "updated_at", nullable = false)
@LastModifiedDate
private Date updatedAt;
//...and so on
}
In my application.yml, I have set the following properties:
spring:
datasource:
url: jdbc:postgresql://localhost:5432/tmt
username: whoever
password: whatever
driver-class-name: org.postgresql.Driver
flyway:
baselineOnMigrate: true
locations: classpath:db/migration
jpa:
hibernate:
ddl-auto: update
generate-ddl: true
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQL10Dialect
jdbc:
lob:
non_contextual_creation: true
This way, I can omit the auditing fields (columns) in my Flyway migration scripts. When I start the application normally on an empty database, the auditing columns created_at and updated_at are being created for every entity that inherits from AuditableEntity.
Now, I want to run my integration test using the @SpringBootTest annotation, so I am expecting the whole application context to be started pretty much the same way. Unfortunately, this is not the case. I am using Zonky's embedded Postgres for tests since I have some JSONB datatypes. Setting it up worked seamlessly, but unfortunately the auditing fields aren't created. My test class looks like this:
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
@AutoConfigureEmbeddedDatabase
@FlywayTest
@Import(PersistenceAuditConfiguration.class)
public class AuthController_IntegrationTest {
//... testy-testy, test, test
}
The first test will insert (register) a new user to my audited users table and return it, but it fails due to the following exception:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is
org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a];
nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
[stack trace omitted]
Caused by: org.postgresql.util.PSQLException: ERROR: column roleentity0_.created_at does not exist
I've found a lot of similar issues, but most dealt with @DataJpaTest and not @SpringBootTest (at this point I don't want to test different layers separately). According to different threads and issues I could find, I've also tried the following:
@EnableJpaAuditing directly on TMTWebApplication config class, which was the first and original way prior to writing integration tests.
@EnableJPAAudidting directly on my test class, which led to a BeanDefinitionOverrideException. After I reluctantly allowed bean overriding, I ran into the above exception again (created_at does not exist).
I can see that there are issues from this and this thread on Github, but I don't yet understand the underlying design of Spring for this particular configuration, and the documentation didn't really help either. Please note: I've asked a similar question to this issue yesterday, but I deleted it. I suspected that it had something to do with Zonky's embedded Postgres instance not understanding the application properties, but I guess that was wrong, so I had to rephrase it to focus on Spring only. I guess, I am missing the forest for all the trees around here, so if someone could point me to the right tree, I'd highly appreciate it. Thanks in advance!