【问题标题】:How do I control spring injections that vary between the test environment and the production environment?如何控制在测试环境和生产环境之间变化的弹簧注入?
【发布时间】:2012-10-17 02:21:12
【问题描述】:

我正在设置一个 CI 情况,我将在其中将我的 Web 应用程序部署到测试环境。在这个测试环境中,我希望应用程序使用的业务对象是真实的模拟;模拟将返回静态测试数据。我正在使用它对我的 ui 运行测试。我正在使用 Spring 控制这些业务对象依赖项的注入;这是一个 struts 2 应用程序,值得。

我认为我的问题与 Maven 相关。让我的 Maven 构建确定是否构建弹簧配置以注入模拟或注入真实事物的最佳方法是什么?这对 Maven 配置文件有用吗?其他选择?

【问题讨论】:

  • 使用配置文件可能是一个不错的选择。您可以拥有一些属性,例如 spring.context,并将其值更改为指向生产上下文文件或测试上下文文件。
  • 这不会导致我的战争工件在 maven repos 中有两个不同版本吗?一种是使用用于测试服务器部署的模拟数据构建的,另一种是使用真实的实时系统设置?

标签: spring maven struts2 continuous-integration integration-testing


【解决方案1】:

Spring 本身支持profiles(如果您使用的是 3.1 或更高版本),对于 web 应用程序,您可以使用 context-parameter 在 web.xml:

<context-param>
   <param-name>spring.profiles.default</param-name>
   <param-value>test</param-value>
</context-param>

编辑:对于 Maven 和 Jenkins,您应该能够为构建作业设置参数,如下所示:

首先,让 Maven 过滤您的 xml-resources(在此示例中,仅过滤以 xml 结尾的文件,其他文件不过滤)通过将以下内容添加到您的 pom.xml 里面&lt;build&gt; &lt;/build&gt; -标签:

    <resources>
        <resource>
            <directory>src/main/webapp</directory>
            <filtering>true</filtering>
            <includes>
                <include>**/*xml</include>
            </includes>
        </resource>
        <resource>
            <directory>src/main/webapp</directory>
            <filtering>false</filtering>
            <excludes>
                <exclude>**/*xml</exclude>
            </excludes>
        </resource>
    </resources> 

然后,在 web.xml 中参数化上下文参数:

<context-param>
   <param-name>spring.profiles.default</param-name>
   <param-value>${env.SPRINGPROFILE}</param-value>
</context-param>

然后在 Jenkins 中参数化构建作业,为 SPRINGPROFILE 设置所需的字符串参数(例如 testprod):https://wiki.jenkins-ci.org/display/JENKINS/Parameterized+Build

【讨论】:

  • 但这仍然需要构建时逻辑来决定如何配置 web.xml 中的值,对吗?
  • @chad:是的,请参阅我编辑的答案。我实际上没有尝试过,因为我无法在家中访问 Jenkins,但我相信它应该可以正常工作。
  • 我想我的问题可能更复杂。我相信您已经给出了实现一个解决方案的好方法,但这是我看到的问题。如果我的测试构建产生了一个内部具有不同配置的战争,那么它将被部署到 maven。但是这个测试数据设置并不是我的团队成员在为他们的开发构建拉下相同的快照依赖项时所期望的;他们希望它脱离正常的业务逻辑。我想也许我的答案更复杂,需要我外部化我的 spring 配置。
  • 也许我可以使用 Spring 配置文件并从我的 web 应用程序外部驱动它们。 . .这个问题(stackoverflow.com/questions/2424118/…)是我得到这个关于外部化配置的想法的地方。
【解决方案2】:

对构建 Web 应用程序工件 (Maven best practice for generating artifacts for multiple environments [prod, test, dev] with CI/Hudson support?) 做任何事情可能是个坏主意。虽然您可以使用各种机制来为不同的上下文生成具有不同 Spring 注入配置的 WAR 文件,但每次构建 WAR 工件时都应该是相同的。

为了从 WAR 中提取配置,我使用了 Spring 3 从外部属性文件中提取覆盖值的能力。我定义了我的业务对象的默认值,即生产值。我配置 spring 来检查属性文件的存在,当应用程序处于测试环境中并且需要模拟注入时,我将部署该文件。如果该属性文件存在,则将其值注入。这是 spring 配置文件的相关位。

<!-- These are the default values -->
    <util:properties id="defaultBeanClasses">
    <prop key="myManagerA">com.myco.ManagerAImpl</prop>
    <prop key="myManagerB">com.myco.ManagerBImpl</prop>
</util:properties>

<!-- Pull in the mock overrides if they exist. -->
<context:property-placeholder 
    location="file:///my/location/mockBeans.properties"
    ignore-resource-not-found="true"
    properties-ref="defaultBeanClasses"/>

<!-- The beans themselves. -->  
<bean id="managerA" class="${myManagerA}"/>
<bean id="managerB" class="${myManagerB}"/>

这是外部“mockBeans.properties”文件的内容:

#Define mock implementations for core managers
myManagerA=com.myco.ManagerAMockImpl
myManagerB=com.myco.ManagerBMockImpl

这很好用。如果您愿意,您甚至可以将 mockBeans.properties 文件包含在实际的 WAR 中,但不能包含在实时位置中。那么测试环境任务也会将它移动到spring config指向的位置。或者,您可以将模拟属性驻留在完全不同的项目中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-18
    • 1970-01-01
    • 1970-01-01
    • 2019-01-16
    相关资源
    最近更新 更多