【问题标题】:Are files in src/test/resources on classpath while application (src/main) is running?应用程序(src/main)运行时,类路径上的 src/test/resources 中的文件是否存在?
【发布时间】:2019-12-21 19:44:58
【问题描述】:

这里是新手! 我在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 Exception: "java.io.FileNotFoundException: resource /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/ 中,数据持久性测试都可以正常工作资源/分贝。但是,这些脚本与测试相关,所以我认为它们不属于应用程序的主要部分。

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

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

【问题讨论】:

  • 您可以从 src/test/ 资源访问 src/main/ 资源,反之则不行。最好将与测试代码相关的类放到 src/test/java 中,而不是使用“test”配置文件。
  • @androberz 这就是规则!?很高兴知道!我发现的每个答案都说这两个位置都在类路径上,仅此而已。关于我的测试,所有相关的类都已经在 src/test/java 中了。我使用 @ActivePRofiles("test") 注释来运行 H2 数据库而不是 mysql 一个。这样,我尝试对来自 H2 数据库的数据进行测试。有用。但看起来主应用程序上下文已启动,因此我无法访问位于 src/test/resource 文件夹中的脚本。难道我做错了什么?我应该修改一些配置还是什么?真的很难找到关于这个主题的像样的文章。

标签: java spring-boot


【解决方案1】:

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

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

我该如何解决这个挑战?

嗯,有很多解决方案:

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

【讨论】:

  • 非常感谢@madhead!正如我已经解释过的,将它们放在 src/main 中似乎有些奇怪,因为它们仅与测试相关。你提到的另一个解决方案我不知道如何实施,但我要谷歌它。
  • @meadhead 还有一件事:以我之前描述的方式组织测试是否有意义,使用内存数据库,用一些数据填充它,然后执行测试?我说的是整个应用程序的集成测试。
  • 这很有意义。许多项目都是这样做的。虽然它不是纯粹的单元测试,但为什么不呢?
  • 如果该资源仅在测试中需要,则将其放在测试资源目录中,不要在主代码库中使用。
  • 感谢您的回答,非常有帮助。我喜欢只将它放在测试资源目录中的想法,但是我怎样才能使用@SpringBootTest 启动我的测试 - 它会启动主应用程序上下文?有更好的解决方案吗?我只是在想,即使我配置 Maven 复制文件,src/main/resource 目录中也会有相同的文件,并且仅用于测试???
猜你喜欢
  • 2015-03-22
  • 1970-01-01
  • 2011-02-24
  • 1970-01-01
  • 2018-09-16
  • 1970-01-01
  • 1970-01-01
  • 2014-09-21
  • 1970-01-01
相关资源
最近更新 更多