Testcontainer无法加载类路径初始化脚本问题求助
Postgres Testcontainer初始化脚本加载失败问题
尝试启动Postgres Testcontainer并通过withInitScript(String)方法加载初始化脚本时,抛出以下错误:
org.testcontainers.ext.ScriptUtils$ScriptLoadException: Could not load classpath init script: /home/ilys/Programming/learn/testHibernate/app/src/test/resources/my_dump.sql. Resource not found.
尽管脚本文件实际存在,仍无法被加载。以下是相关信息及解决方案:
依赖配置
dependencies { implementation 'org.springframework.boot:spring-boot-starter' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation group: 'org.reflections', name: 'reflections', version: '0.10.2' implementation group: 'org.postgresql', name: 'postgresql', version: '42.6.0' compileOnly 'org.projectlombok:lombok:1.18.28' annotationProcessor 'org.projectlombok:lombok:1.18.28' developmentOnly 'org.springframework.boot:spring-boot-devtools' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.boot:spring-boot-testcontainers' testImplementation 'org.testcontainers:junit-jupiter' testImplementation group: 'org.testcontainers', name: 'postgresql', version: '1.19.4' }
Testcontainer初始化代码
@Container static PostgreSQLContainer<?> postgres; static { File dump = new File("src/test/resources/my_dump.sql"); System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); System.out.println("DUMP FILE ABS PATH: " + dump.getAbsolutePath()); System.out.println("DUMP FILE EXISTS: " + dump.exists()); postgres = new PostgreSQLContainer<>("postgres:15") .withUsername("postgres") .withPassword("pass") .withExposedPorts(5432) .withInitScript(dump.getAbsolutePath()) .withDatabaseName("postgres"); }
运行输出
> Task :common:compileJava UP-TO-DATE > Task :app:compileJava > Task :app:processResources UP-TO-DATE > Task :app:classes > Task :app:compileTestJava > Task :app:processTestResources UP-TO-DATE > Task :app:testClasses > Task :common:processResources NO-SOURCE > Task :common:classes UP-TO-DATE > Task :common:jar UP-TO-DATE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DUMP FILE ABS PATH: /home/ilys/Programming/learn/testHibernate/app/src/test/resources/my_dump.sql DUMP FILE EXISTS: true 11:50:15.079 [Test worker] INFO org.testcontainers.utility.ImageNameSubstitutor -- Image name substitution will be performed by: DefaultImageNameSubstitutor (composite of 'ConfigurationFileImageNameSubstitutor' and 'PrefixingImageNameSubstitutor') 11:50:15.173 [Test worker] INFO org.testcontainers.dockerclient.DockerClientProviderStrategy -- Loaded org.testcontainers.dockerclient.UnixSocketClientProviderStrategy from ~/.testcontainers.properties, will try it first 11:50:15.267 [Test worker] INFO org.testcontainers.dockerclient.DockerClientProviderStrategy -- Found Docker environment with local Unix socket (unix:///var/run/docker.sock) 11:50:15.268 [Test worker] INFO org.testcontainers.DockerClientFactory -- Docker host IP address is localhost 11:50:15.276 [Test worker] INFO org.testcontainers.DockerClientFactory -- Connected to docker: Server Version: 24.0.7 API Version: 1.43 Operating System: Manjaro Linux Total Memory: 64031 MB 11:50:15.291 [Test worker] INFO tc.testcontainers/ryuk:0.5.1 -- Creating container for image: testcontainers/ryuk:0.5.1 11:50:15.376 [Test worker] INFO tc.testcontainers/ryuk:0.5.1 -- Container testcontainers/ryuk:0.5.1 is starting: db2b087f633ba2310499f02692f762974c07ff594efbc5ae126d5eac8db9f9a4 11:50:15.629 [Test worker] INFO tc.testcontainers/ryuk:0.5.1 -- Container testcontainers/ryuk:0.5.1 started in PT0.349619688S 11:50:15.632 [Test worker] INFO org.testcontainers.utility.RyukResourceReaper -- Ryuk started - will monitor and terminate Testcontainers containers on JVM exit 11:50:15.632 [Test worker] INFO org.testcontainers.DockerClientFactory -- Checking the system... 11:50:15.632 [Test worker] INFO org.testcontainers.DockerClientFactory -- ✔︎ Docker server version should be at least 1.6.0 11:50:15.633 [Test worker] INFO tc.postgres:15 -- Creating container for image: postgres:15 11:50:15.677 [Test worker] INFO tc.postgres:15 -- Container postgres:15 is starting: c7d3772fddcddf6d7aaaa60e4170edf95dc609b353317de1d291a2575bd25a8c 11:50:16.558 [Test worker] INFO tc.postgres:15 -- Container postgres:15 started in PT0.925549685S 11:50:16.559 [Test worker] INFO tc.postgres:15 -- Container is started (JDBC URL: jdbc:postgresql://localhost:32797/postgres?loggerLevel=OFF) 11:50:16.560 [Test worker] WARN org.testcontainers.ext.ScriptUtils -- Could not load classpath init script: /home/ilys/Programming/learn/testHibernate/app/src/test/resources/my_dump.sql 11:50:16.560 [Test worker] ERROR tc.postgres:15 -- Could not start container org.testcontainers.ext.ScriptUtils$ScriptLoadException: Could not load classpath init script: /home/ilys/Programming/learn/testHibernate/app/src/test/resources/my_dump.sql. Resource not found.
初始化脚本内容
CREATE TABLE IF NOT EXISTS public.first_table ( id bigserial not null, val text not null, constraint pk_setting_value primary key (id) ); INSERT INTO first_table(val) values ('1234_test'); INSERT INTO first_table(val) values ('2345_test'); INSERT INTO first_table(val) values ('3456_test'); INSERT INTO first_table(val) values ('4567_test');
解决方案
核心原因
withInitScript(String)方法的参数被Testcontainers当作类路径资源路径处理,而非本地文件系统的绝对路径。即使文件存在,也会从类路径中查找而非本地路径。
方法1:使用类路径相对路径
由于脚本已放在src/test/resources目录下(该目录会被加入类路径),直接传入相对路径即可:
postgres = new PostgreSQLContainer<>("postgres:15") .withUsername("postgres") .withPassword("pass") .withExposedPorts(5432) .withInitScript("my_dump.sql") // 类路径相对路径 .withDatabaseName("postgres");
方法2:复制本地文件到容器执行
如果必须使用本地绝对路径,改用withCopyFileToContainer()将脚本复制到Postgres容器的初始化目录,容器启动时会自动执行该目录下的SQL:
postgres = new PostgreSQLContainer<>("postgres:15") .withUsername("postgres") .withPassword("pass") .withExposedPorts(5432) .withDatabaseName("postgres") .withCopyFileToContainer(MountableFile.forHostPath(dump.getAbsolutePath()), "/docker-entrypoint-initdb.d/my_dump.sql");
内容的提问来源于stack exchange,提问作者mamol
相关产品推荐
相关产品推荐

