当应用程序(src/main)运行时,src/test/resources 中的文件是否位于类路径上?

Ned*_*dim 4 java spring-boot

新手在这里!我在SO上发现了很多类似的问题,但没有一个给我一个明确的答案。

我为所有层编写了测试,包括我的 spring-boot 应用程序中的持久层。为了测试持久层,我使用了 H2 数据库。我使用 @DataJpaTest 注释并将 schema.sql 和 data.sql 脚本放置到 src/test/resources/db 文件夹中以创建模式并使用 data.sql 中的数据填充它。它工作得很好,所有测试都通过使用该数据。

现在我想做的是使用 @SpringBootTest 设置集成测试来测试整个应用程序 - 从上到下,从 Web 层到数据层。我使用 H2 配置制作了 application-test.properties 并使用 @ActiveProfiles("test") 注释了我的测试类,并且它工作正常。当我运行这个测试类时,应用程序上下文启动,H2 也启动,但是当然,那里没有数据。我想使用 src/test/resources/db 中的 data.sql 中的相同日期填充内存数据库。

我以这种方式修改了 application-test.properties: spring.datasource.url=jdbc:h2:mem:testdb;INIT=RUNSCRIPT FROM 'classpath:db/schema.sql'\;RUNSCRIPT FROM 'classpath:db/data.sql ',我得到了 org.h2.jdbc.JdbcSQLNonTransientException:IO 异常:“java.io.FileNotFoundException:资源/db/schema.sql”异常。

我做了很多谷歌搜索,发现更多资源说 src/main/resources 和 src/test/resources 都在类路径上。如果是这样,为什么我会得到这个例外?

另外,当我将这两个脚本放入 src/main/resources/db 时,它工作正常。另外,当我运行持久层测试时,无论这些脚本位于 src/main/resources/db 还是 src/test/resources/db 中,它都可以正常工作。所以,它看起来像是一个使用 src/main/resources 和 src/test/resources 位置作为类路径的测试环境,但该环境仅使用 src/main/resources 作为类路径!?这是真的吗?

我尝试过的一种可能的解决方案及其工作原理是在测试之前不要运行这些脚本(从 .properties 文件中删除 INIT=RUNSCRIPT FROM 'classpath:db/schema.sql'\;RUNSCRIPT FROM 'classpath:db/data.sql' )以编程方式创建一些对象并将它们保存到数据库,然后编写测试,但我认为从脚本填充数据比在每个测试类中编写此代码更容易和更精简。

另一个可能的解决方案是将这些脚本从 src/test/resources/db 复制到 src/main/resources/db ,但这意味着我会有重复的数据,我讨厌这样。此外,这意味着更难维护。

下一个可能的解决方案是将这些脚本放在 src/main/resources/db 中,因为正如我所说,无论这些脚本位于 src/main/resources/db 还是 src/test/resources/db 中,数据持久性测试都可以正常工作。但是,这些脚本与测试相关,所以我认为它们属于那里而不是应用程序的主要部分。

而且,如果我提供这些脚本的绝对路径,它可以正常工作,但这意味着我的团队成员必须修改它以适应他们的机器。并不是真正的最佳解决方案。

所以,我的问题是: 1.测试环境是否同时使用 src/main/resources 和 src/test/resources 位置作为类路径,但主环境仅使用 src/main/resources 作为类路径?2. 我该如何解决这个挑战?

mad*_*ead 6

测试环境是否同时使用src/main/resourcessrc/test/resources位置作为类路径,但主环境仅使用src/main/resources作为类路径?

是的。是真的。在 Maven 和 Gradle 中,test类路径是继承的main,反之亦然。这意味着来自src/main/java和 的类和资源src/main/resources在测试执行期间可用,但主代码库无法访问src/test/java和。src/test/resources另请注意,测试类和资源不可传递,即它们在依赖的项目中不可用。

我该如何解决这个挑战?

嗯,有很多解决方案:

  1. 将资源放入src/main(显然)
  2. 将两个地方需要的资源提取到一个单独的模块中并依赖它。
  3. 使用maven-resources-plugin从其他位置复制文件。