Answers:
对于Postgres,这是不可能的。它不提供像HSQLDB或MySQL这样的进程内/内存引擎。
如果要创建一个独立的环境,可以将Postgres二进制文件放入SVN中(但它不仅仅是一个可执行文件)。
您将需要运行initdb来设置测试数据库,然后才能执行任何操作。可以从批处理文件或使用Runtime.exec()完成此操作。但是请注意,initdb并不是很快。您绝对不希望为每个测试都运行该程序。不过,在测试套件之前,您可能会逃避运行此操作。
但是,尽管可以做到这一点,但我建议安装专用的Postgres安装程序,您可以在运行测试之前简单地重新创建测试数据库。
通过使用使创建它相当快(一个模板数据库您可以重新创建测试数据库很多快于每个测试运行运行initdb)
testcontainers
,该工具从根本上让您的测试启动公司成为了一个废弃的,docker化的postgres-instance。见github.com/testcontainers/testcontainers-java/blob/master/...
(将我的答案从使用内存中的PostgreSQL进行推广):
我不知道如何运行内存Postgres数据库进行测试。可能吗?
不,这是不可能的。PostgreSQL用C实现,并编译为平台代码。与H2或Derby不同,您不能只加载jar
并将其作为一次性内存DB启动。
与SQLite也使用C语言编写并编译为平台代码不同,PostgreSQL也不能在进程中加载。它需要多个进程(每个连接一个),因为它是一个多处理而非多线程的体系结构。多重处理要求意味着您必须将邮局主管作为独立进程启动。
我建议只编写测试以期望特定的主机名/用户名/密码可以正常工作,并让测试利用CREATE DATABASE
一次性数据库,然后DROP DATABASE
在运行结束时进行测试。从属性文件获取数据库连接详细信息,构建目标属性,环境变量等。
使用已经拥有数据库的现有PostgreSQL实例是安全的,只要提供给单元测试的用户不是超级用户,而只有超级用户即可CREATEDB
。最糟糕的是,您将在其他数据库中造成性能问题。因此,我更喜欢运行一个完全隔离的PostgreSQL安装进行测试。
或者,如果你真的热衷,你可以有你的测试工具定位initdb
和postgres
二进制文件,运行initdb
创建数据库,修改pg_hba.conf
到trust
,运行postgres
启动它一个随机端口上,创建一个用户,创建一个数据库,并运行测试。您甚至可以将多个体系结构的PostgreSQL二进制文件捆绑在一个jar中,然后将当前体系结构的PostgreSQL二进制文件解压缩到一个临时目录,然后再运行测试。
我个人认为这是应避免的主要痛苦;只需配置一个测试数据库就更容易了。然而,它已经成为与的来临更容易一些include_dir
支持postgresql.conf
; 现在您只需追加一行,然后为其余所有内容编写一个生成的配置文件。
有关如何安全地提高PostgreSQL性能以进行测试的更多信息,请参阅我之前在该主题上写的详细答案:优化PostgreSQL以进行快速测试
某些人改为使用PostgreSQL方言模式的H2数据库来运行测试。我认为这几乎与使用SQLite进行测试并使用PostgreSQL进行生产部署的Rails人员一样糟糕。
H2支持某些PostgreSQL扩展并模拟PostgreSQL方言。但是,仅此而已-一个仿真。您会发现H2接受查询但PostgreSQL不接受查询的地方,行为不同的地方等等。在撰写本文时,您还会发现PostgreSQL支持H2不能做的很多事情-例如窗口函数。
如果您了解这种方法的局限性并且您的数据库访问很简单,那么H2可能就可以了。但是在那种情况下,您可能更适合抽象ORM的ORM,因为您无论如何都不会使用其有趣的功能-在这种情况下,您不必再在乎数据库兼容性。
千万不能使用表空间来创建一个“内存”数据库。这不仅是不必要的,因为它无论如何都无法显着提高性能,它还是一种中断对同一PostgreSQL安装中您可能关心的其他任何对象的访问的好方法。9.4文档现在包含以下警告:
警告
即使位于主PostgreSQL数据目录之外,表空间还是数据库集群的组成部分,不能视为数据文件的自治集合。它们取决于主数据目录中包含的元数据,因此不能附加到其他数据库集群或单独备份。同样,如果丢失表空间(文件删除,磁盘故障等),则数据库集群可能变得不可读或无法启动。将表空间放在诸如ramdisk的临时文件系统上会危及整个群集的可靠性。
因为我注意到太多的人正在这样做并遇到麻烦。
(如果完成了此操作,则可以mkdir
缺少的表空间目录来使PostgreSQL重新启动,然后DROP
是缺少的数据库,表等。最好不要这样做。)
initdb
在那里安装一个全新的Pg。但是,实际上,为在普通存储上进行快速测试而调整的Pg(fsync = off和其他数据持久性/安全性功能已关闭)与在ramdisk上运行(至少在Linux上)几乎没有区别。
或者,您可以在ramfs / tempfs中创建一个TABLESPACE,并在那里创建所有对象。
最近我被指给我一篇关于在Linux上完全做到这一点的文章。
这可能危及整个数据库集群的完整性。
阅读手册中添加的警告。
因此,这只是消耗性数据的一种选择。
对于单元测试,它应该可以正常工作。如果要在同一台计算机上运行其他数据库,请确保使用单独的数据库集群(具有自己的端口)以确保安全。
initdb
是tempfs或ramdisk中的新postgres实例。难道不是在tempfs等使用的表空间,它是脆弱的和毫无意义的。您最好使用普通的表空间并创建UNLOGGED
表-它将执行类似的操作。除非您采取可能冒着损害整个数据库完整性的措施,否则它不会解决WAL性能和fsync因素(请参阅stackoverflow.com/q/9407442/398670)。不要这样
现在可以通过OpenTable中的嵌入式PostgreSQL组件在JUnit测试中运行PostgreSQL的内存实例:https : //github.com/opentable/otj-pg-embedded。
通过将依赖项添加到otj-pg-embedded库(https://mvnrepository.com/artifact/com.opentable.components/otj-pg-embedded)中,您可以在@Before和@Afer钩子:
EmbeddedPostgres pg = EmbeddedPostgres.start();
他们甚至提供了一个JUnit规则来自动让JUnit为您启动和停止PostgreSQL数据库服务器:
@Rule
public SingleInstancePostgresRule pg = EmbeddedPostgresRules.singleInstance();
@Rule
用@ExtendWith
?只需使用.start()
的@BeforeAll
?
DataSource embeddedPostgresDS = EmbeddedPostgres.builder().start().getPostgresDatabase();
您可以使用TestContainers来启动PosgreSQL docker容器进行测试:http ://testcontainers.viewdocs.io/testcontainers-java/usage/database_containers/
TestContainers提供一个JUnit @ Rule / @ ClassRule:此模式在测试之前启动容器内的数据库,然后将其拆除。
例:
public class SimplePostgreSQLTest {
@Rule
public PostgreSQLContainer postgres = new PostgreSQLContainer();
@Test
public void testSimple() throws SQLException {
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setJdbcUrl(postgres.getJdbcUrl());
hikariConfig.setUsername(postgres.getUsername());
hikariConfig.setPassword(postgres.getPassword());
HikariDataSource ds = new HikariDataSource(hikariConfig);
Statement statement = ds.getConnection().createStatement();
statement.execute("SELECT 1");
ResultSet resultSet = statement.getResultSet();
resultSet.next();
int resultSetInt = resultSet.getInt(1);
assertEquals("A basic SELECT query succeeds", 1, resultSetInt);
}
}
现在有一个来自俄罗斯搜索公司Yandex的PostgreSQL内存版本:https://github.com/yandex-qatools/postgresql-embedded
它基于Flapdoodle OSS的嵌入过程。
使用示例(来自github页面):
// starting Postgres
final EmbeddedPostgres postgres = new EmbeddedPostgres(V9_6);
// predefined data directory
// final EmbeddedPostgres postgres = new EmbeddedPostgres(V9_6, "/path/to/predefined/data/directory");
final String url = postgres.start("localhost", 5432, "dbName", "userName", "password");
// connecting to a running Postgres and feeding up the database
final Connection conn = DriverManager.getConnection(url);
conn.createStatement().execute("CREATE TABLE films (code char(5));");
我正在使用它一段时间。效果很好。
更新:此项目不再得到积极维护
Please be adviced that the main maintainer of this project has successfuly
migrated to the use of Test Containers project. This is the best possible
alternative nowadays.
如果您使用的是NodeJS,则可以使用pg-mem(免责声明:我是作者)来模仿postgres db的最常见功能。
您将拥有完整的内存中,独立于平台且与平台无关的数据库复制PG行为(它甚至可以在浏览器中运行))。
我写了一篇文章,以展示如何为你的单元测试使用它在这里。