如何使用 SpringBootTest 启用 JPA 审计?

Ser*_*bst 9 java auditing spring-data-jpa spring-boot spring-boot-test

我想为我的 RestAPI 端点编写集成测试,但我正在努力解决 @EnableJpaAuditing。我希望 Spring 审核我的一些实体,因此我创建了以下配置类:

@Configuration
@EnableJpaAuditing
public class PersistenceAuditConfiguration {

}
Run Code Online (Sandbox Code Playgroud)

我将其导入到我的主应用程序配置中:

@ServletComponentScan
@SpringBootApplication
@Import(PersistenceAuditConfiguration.class)
public class TMTWebApplication {

    public static void main(String[] args)  {
        SpringApplication.run(TMTWebApplication.class, args);
    }
}
Run Code Online (Sandbox Code Playgroud)

另外,我有一个针对我想要审核的所有实体的抽象基类:

@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

}
Run Code Online (Sandbox Code Playgroud)

在我的application.yml中,我设置了以下属性:

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
Run Code Online (Sandbox Code Playgroud)

这样,我可以在 Flyway 迁移脚本中省略审核字段(列)。当我在空数据库上正常启动应用程序时,将为从 AuditableEntity 继承的每个实体创建审核列created_atupdated_at 。

现在,我想使用 @SpringBootTest 注释运行集成测试,因此我期望整个应用程序上下文以几乎相同的方式启动。不幸的是,这种情况并非如此。我使用 Zonky 的嵌入式 Postgres 进行测试,因为我有一些 JSONB 数据类型。设置工作无缝进行,但不幸的是未创建审核字段。我的测试类如下所示:

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
@AutoConfigureEmbeddedDatabase
@FlywayTest
@Import(PersistenceAuditConfiguration.class)
public class AuthController_IntegrationTest {

    //... testy-testy, test, test

}
Run Code Online (Sandbox Code Playgroud)

第一个测试将向我的审核用户表插入(注册)一个新用户并返回它,但由于以下异常而失败:

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
Run Code Online (Sandbox Code Playgroud)

我发现了很多类似的问题,但大多数都处理 @DataJpaTest 而不是 @SpringBootTest (此时我不想单独测试不同的层)。根据我能找到的不同线程和问题,我还尝试了以下方法:

  • 直接在 TMTWebApplication 配置类上@EnableJpaAuditing,这是编写集成测试之前的第一个也是原始的方法。

  • 直接在我的测试类上@EnableJPAAudidting,这导致了 BeanDefinitionOverrideException。在我不情愿地允许bean重写之后,我再次遇到了上面的异常(created_at不存在)。

我可以看到 Github 上的这个这个线程存在问题,但我还不了解 Spring 对于这个特定配置的底层设计,并且文档也没有真正的帮助。请注意:我昨天问了一个与此问题类似的问题,但我删除了它。我怀疑这与 Zonky 的嵌入式 Postgres 实例不理解应用程序属性有关,但我想这是错误的,所以我不得不重新表述它以仅关注 Spring。我想,我错过了这里周围所有树木的森林,所以如果有人能指出我正确的树,我将非常感激。提前致谢!