使用不同的 Spring 属性进行集成测试

发布于 2024-09-06 10:48:32 字数 1195 浏览 3 评论 0原文

我正在使用 Selenium 测试一个使用 Spring 开发的 Web 应用程序,以检查该 Web 应用程序是否为用户显示正确的内容,以及他是否能够执行规范中的所有操作。

其他开发人员使用假的 Hibernate 内存数据库 (HSQLDB) 进行单元测试。显然,我必须使用程序使用的真实数据库进行测试。 Spring 应用程序上下文的 JDBC 参数由 Spring 在运行时(或构建 WAR 文件的编译时)加载。 Spring 使用 org.springframework.beans.factory.config.PropertyPlaceholderConfigurer 找到的属性来配置 webapp 和测试的应用程序上下文,并且 XML 配置文件由测试和 webapp 共享。

根据 Maven 配置文件、单元测试或集成测试,属性需要有所不同。

我尝试了多种方法,但没有成功:

  • 使用较低级别的 SQL 查询开发我自己的 DAO。这确实是浪费时间,也是最后的解决方案。由于外键约束和数据库模型更改,并且考虑到应用程序具有相当可靠(经过单元测试)的 DAO 集,这确实是最愚蠢的选择。
  • 使用 Maven 过滤器并在那里定义 JDBC 属性。问题是属性在主应用程序和单元测试之间共享,因为 tomcat:redeploy 目标包括单元测试。然后应用程序无法连接到真实的数据库。
  • 不同的文件夹有不同的属性。 Spring 根本不关心配置文件的 Surefire 配置中定义的附加资源,无论是使用 testResources 还是 resources。奇怪的是,这种方法对于主应用程序中的每个环境具有不同的 JDBC 参数非常有效。我们在 src/main/resources 中有几个文件夹,其中包含覆盖 src/main/resources 中默认属性的属性。它只是与 src/test/resources 的工作方式不同。我什至不知道如何找到这种行为的原因。
  • 让 Spring 根据用户定义的 Maven 参数加载不同的属性文件。主应用程序和单元测试使用相同的属性。当 Spring 找不到属性文件时也会抱怨(迫使我创建带有空文件的目录只是为了完成构建)。

为什么当前的构建配置,开发人员配置文件(开发人员,测试服务器...)+测试配置文件(单元测​​试)同时激活,并且属性不相互覆盖?因为Maven会让Spring在启动单元测试时查看src/test/resources,在启动构建目标时查看src/main/resources。不幸的是,像这样的集成测试没有默认配置。

I am testing with Selenium a web application developed with Spring to check that the web application displays the right stuff for the user and that he's able to do everything that is in the specification.

The other developers are using a fake Hibernate database in memory (HSQLDB) for unit testing. I have to use the real DB used by the program for testing, obviously. The JDBC parameters for the Spring application context are loaded by Spring at runtime (or compile time for building the WAR file). Spring use properties found by org.springframework.beans.factory.config.PropertyPlaceholderConfigurer to configure the application context for the webapp and the tests, and the XML configuration files are shared by the tests and the webapp.

The properties need to be different depending on the Maven profile, unit tests or integration tests.

I tried several approaches, without success:

  • developing my own DAO's using lower-level SQL queries. It's a real waste of time and solution of last resort. Because of the foreign key constraints and database model changes, and given that the application has a pretty solid (unit-tested) set of DAO's, it's really the dumbest option.
  • using Maven filters and define the JDBC properties there. The problem is that the properties are shared between the main application and the unit tests, because the tomcat:redeploy goal include unit tests. The application then cannot connect to the real DB.
  • having different properties in different folders. Spring doesn't care at all about the additional resources defined in the profiles' Surefire configuration, either with testResources or resources. The strange thing is that this approach works perfectly well for having different JDBC parameters for each environment in the main app. We have several folders in src/main/resources which contains properties overriding the default properties in src/main/resources. It just doesn't work the same way for src/test/resources. I don't even know how I could find the cause of this behavior.
  • have Spring loading different property files based on user-defined Maven parameters. The same properties are used for the main app and the unit tests. Spring also complain when it cannot find the properties files (forcing me to create directories with empty files just to get the build completing).

Why is the current build configuration, with the developer profile (developer, test server...) + the test profile (unit tests) activated at the same time running and the properties not overriding one another? Because Maven will make Spring look at src/test/resources when the unit tests are launched and src/main/resources when the build goal is launched. Unfortunately, there is no default configuration for integration tests like this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我是男神闪亮亮 2024-09-13 10:48:32

我们这样做的方式是基于变量来选择属性文件,因此 spring 中的属性占位符如下所示:

<context:property-placeholder location="classpath:db.${TARGET_ENV}.properties" />

然后您可以选择将 TARGET_ENV 定义为环境变量或使用 -DTARGET_ENV= 将其传递给 maven。 ..

The way we do it is base the selection of the properties file off a variable, so property place holder in spring looks like this:

<context:property-placeholder location="classpath:db.${TARGET_ENV}.properties" />

And then you have a choice of defining TARGET_ENV as an environment variable or passing it to maven using -DTARGET_ENV=...

会傲 2024-09-13 10:48:32

对于单元测试,您可能拥有与生产中名称相同的属性文件,该文件将覆盖生产文件,因为它位于类路径中的较早位置。
例如,您可能在 src/main/resources/my.properties 处拥有生产属性,并在 src/test/resources/my.properties 处拥有用于单元测试的覆盖文件。

好的做法是拥有一个仅包含环境设置(主机/端口)的单独属性文件以及使用特定于环境的值的其他特定于应用程序的属性文件。那么环境特定文件是您需要更改的唯一文件。
对于集成测试,您还可以在类路径中拥有特定的属性文件。

此外,生产工件内不应有特定于环境的设置。它们应该分开放置。

您可以尝试的另一件事是使用 spring @Profile。但使用它们时,您会在代码中放置一些非生产设置,这是一种不好的做法。

For unit tests you may have the property file with same name as in production which will override production one since it's earlier in classpath.
e.g. you may have production properties at src/main/resources/my.properties and overriding file for unit tests at src/test/resources/my.properties.

The good practice is to have a separate property file with environment settings only (hosts/ports) and other application-specific property files that are using values from environment-specific one. Then environment specific file is the only file you need to change.
For integration testing you may also have specific property file in the classpath.

Also, there should be no environment-specific settings inside production artifacts. They should be located separately.

One more thing you may try is to use spring @Profiles. But using them you put some non-production settings in your code which is a bad practice.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文