【问题标题】:How to perform unit tests with h2 database where bpchar is used?如何使用使用 bpchar 的 h2 数据库执行单元测试?
【发布时间】:2019-10-19 09:43:41
【问题描述】:
我有一个使用 postgres 数据库的 spring + hibernate 应用程序。我需要为控制器编写单元测试。对于测试,我想使用 h2 数据库,但不幸的是在 create-drop 期间测试崩溃,给我留下了 bpchar 数据类型无效的信息。我想知道如何解决这个问题,以便我可以运行测试。
我无法将使用 bpchar 的列更改为 varchar,它需要保持原样。我也尝试设置 postgresql 模式,但没有帮助。
我唯一的解决方案是使用嵌入式 postgres 数据库来执行测试,或者我可以使用其他任何方法吗?
【问题讨论】:
标签:
java
spring
postgresql
testing
h2
【解决方案1】:
我唯一的解决方案是使用嵌入式 postgres 数据库来执行测试,或者我可以使用其他任何方法吗?
您尝试将 postgres 特定的数据类型与 h2 (没有它)一起使用。当然,它不起作用。
如果您无法更改此字段的类型 - 在测试中使用嵌入式 postgres。
【解决方案2】:
实际上你可以在你的 application.properties 中这样做让 H2 知道:
spring.datasource.url=jdbc:h2:mem:testdb;INIT=CREATE TYPE BPCHAR AS CHARACTER NOT NULL
还要确保为您的测试关闭数据库的自动配置。您可以通过添加:
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class MyTestForTableWithBpcharColumn {
【解决方案3】:
解决这个问题的一个有趣的方法是Test Containers
由于 Postgres 没有嵌入式模式,但您可以使用上述框架在测试之前启动 docker 容器,如果您使用 Flyway 或 Liquibase 之类的东西或集成您的自定义解决方案,则可以创建架构并应用迁移.
这个想法是容器将在运行时准备好并可供测试使用。
测试通过后(无论实际结果如何,成功或失败)都可以停止容器。
启动容器可能非常昂贵(几秒钟),但是您可以在测试期间利用弹簧缓存配置,因此当模块中的第一个测试开始时,容器实际上已启动,但是,它在测试和测试用例之间重复使用,因为应用程序上下文不会重新启动。
由于您在测试用例上放置了 Spring 的 @Transactional 注释,因此在测试之间保持数据库清洁也成为一项微不足道的任务,因此 Spring 在每次测试后人为地回滚事务。由于在 Postgres 中,即使是 DDL 命令也可以是事务性的,它应该已经足够好了。
这种方法的唯一限制是,如果您计划在本地运行这些测试,您应该在构建机器或本地开发机器上使用 docker(在 Linux 和 Mac OS 上这不是问题,但在 Windows至少需要有 Windows 10 专业版才能安装 docker 环境)。
我在实际项目中使用过这种方法,发现它对集成测试非常有效。