我想为我的 RestAPI 端点编写集成测试,但我正在努力解决 @EnableJpaAuditing。我希望 Spring 审核我的一些实体,因此我创建了以下配置类:
@Configuration
@EnableJpaAuditing
public class PersistenceAuditConfiguration {
}
我将其导入到我的主应用程序配置中:
@ServletComponentScan
@SpringBootApplication
@Import(PersistenceAuditConfiguration.class)
public class TMTWebApplication {
public static void main(String[] args) {
SpringApplication.run(TMTWebApplication.class, args);
}
}
此外,我有一个用于我想要审核的所有实体的抽象基类:
@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
}
在我的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
这样,我可以在 Flyway 迁移脚本中省略审核字段(列)。当我在空数据库上正常启动应用程序时,将为继承自 AuditableEntity 的每个实体创建审核列 created_at 和 updated_at。
现在,我想使用 @SpringBootTest 注释运行集成测试,因此我期望整个应用程序上下文以几乎相同的方式启动。不幸的是,事实并非如此。我使用 Zonky 的嵌入式 Postgres 进行测试,因为我有一些 JSONB 数据类型。设置工作无缝进行,但不幸的是未创建审核字段。我的测试课如下所示:
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
@AutoConfigureEmbeddedDatabase
@FlywayTest
@Import(PersistenceAuditConfiguration.class)
public class AuthController_IntegrationTest {
//... testy-testy, test, test
}
第一个测试将向我的审核用户表插入(注册)一个新用户并返回它,但由于以下异常而失败:
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
我发现了很多类似的问题,但大多数都处理@DataJpaTest而不是@SpringBootTest(此时我不想单独测试不同的层)。根据我能找到的不同线索和问题,我还尝试了以下方法:
this 和 this 线程存在问题,但我还不了解 Spring 针对此特定配置的底层设计,并且文档也没有真正帮助。 请注意:我昨天问过与此问题类似的问题,但我删除了它。我怀疑这与 Zonky 的嵌入式 Postgres 实例不理解应用程序属性有关,但我想这是错误的,所以我不得不重新表述它以仅关注 Spring。我想,我错过了这里周围所有树木的森林,所以如果有人能指出我正确的树,我将非常感激。预先感谢!
@SpringBootTest
在集成测试中启用 JPA 审核,请按照以下步骤操作:
启用 JPA 审核:将 @EnableJpaAuditing
直接添加到您的测试类。
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
@AutoConfigureEmbeddedDatabase
@FlywayTest
@EnableJpaAuditing
public class AuthController_IntegrationTest {
// Your test methods
}
允许 Bean 定义覆盖:如果遇到 BeanDefinitionOverrideException
,请通过将其添加到您的
application-test.yml
来允许 Bean 覆盖:
spring:
main:
allow-bean-definition-overriding: true
检查数据库初始化:确保使用实体定义正确初始化嵌入式 PostgreSQL 数据库。查找指示表创建的日志。
验证 Flyway 迁移:确保 Flyway 迁移正确应用于嵌入式数据库。检查测试日志中的迁移历史记录。