【问题标题】:Unitils: How can it obtain database properties from SpringUnitils:如何从 Spring 获取数据库属性
【发布时间】:2014-09-30 14:42:17
【问题描述】:

我使用 Unitils 和 Spring 进行单元测试。我已经使用属性文件为 Spring 配置了数据源。

我的问题是如何为 Unitils 使用相同的数据源或相同的属性?

Unitils 需要类路径 unitils.properties 中的文件,其中包含 url、用户、密码和驱动程序等数据库配置参数。

我尝试使用 Spring 配置中使用的属性来配置 Unitils,如下所示,但它不起作用。

database.driverClassName=${jdbc.driver.class}

谢谢, 阿迪

【问题讨论】:

    标签: spring unit-testing unitils


    【解决方案1】:

    一个潜在的解决方案...您可以让您的 Spring 配置从 unitils.properties 读取其数据源参数,而不是相反。可能不太理想。

    我相信 unitils 在幕后使用了 spring,因此您也可以尝试使用 @SpringApplicationContext 在您的 unitils 测试中添加数据源上下文。如果您可以在 unitils 启动时确定数据源 bean 设置的名称,则可以在您的上下文中覆盖它(假设 unitils 数据源 bean 是在其他 spring bean 之前创建的,这可能/可能不是真的。) /p>

    例如

    @SpringApplicationContext({"correctDataSourceContext.xml"})

    编辑:另一个肯定会起作用的选项:https://stackoverflow.com/a/6561782/411229 基本上自己实例化 Unitils 并手动设置属性。

    【讨论】:

      【解决方案2】:

      尽管我使用了不同的方法,但 Ryan 的回答是正确且有用的。

      我扩展了PropertiesDataSourceFactory ro类,重写方法如下:

      public class UnitilsDataSourceFactory extends PropertiesDataSourceFactory {
      
          @Override
          public void init(Properties configuration) {
              try {
                  String[] configFiles = new String[] { "applicationContext-test.xml" };
                  BeanFactory factory = new ClassPathXmlApplicationContext(configFiles);
      
                  SystemPropertiesReader systemPropertiesReader = (SystemPropertiesReader) factory.getBean("systemPropertiesReader");
                  Properties loadProperties = systemPropertiesReader.loadProperties();
      
                  super.init(loadProperties);
              } catch (Exception e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
              }
          }
      
          @Override
          public DataSource createDataSource() {
              DataSource dataSource = super.createDataSource();
              return dataSource;
          }
      
      }
      

      还写了一个 SystemPropertiesReader 为:

      public class SystemPropertiesReader {
      
          private Collection<Resource> resources;
      
          public void setResources(final Collection<Resource> resources) {
              this.resources = resources;
          }
      
          public void setResource(final Resource resource) {
              resources = Collections.singleton(resource);
          }
      
          @PostConstruct
          public Properties loadProperties() throws Exception {
              final Properties systemProperties = System.getProperties();
              for (final Resource resource : resources) {
                  final InputStream inputStream = resource.getInputStream();
                  try {
                      systemProperties.load(inputStream);
                  } finally {
                      //
                  }
              }
      
              return systemProperties;
          }
      
      }
      

      并添加了一个带有属性文件的bean:

      <bean id="systemPropertiesReader" class="uk.co.friendslife.eventmanager.domain.dao.SystemPropertiesReader">
                  <property name="resource">
                      <value>classpath:/META-INF/em/config/eventmanager_${database_name_lower}.properties</value>
                  </property>
      </bean>
      

      将以下内容添加到 unitils.properties:

      org.unitils.database.config.DataSourceFactory.implClassName=x.y.UnitilsDataSourceFactory
      

      【讨论】:

        【解决方案3】:

        只是想补充一些想法,我不确定这是否是最佳实践,或者如果有什么问题就不要纠正我。

        • 我的项目
          -src
          --TestPackage
          ---BaseServiceTest.class
          ---BlogspotServiceTest.class
          --hibernate.cfg.xml
          -网络
          --WEB-INF
          ---blogspot-servlet-test.xml
          ---jdbc-test.properties

        在我的例子中,我使用我的 blogspot-servlet-test.xml 来调用或创建数据源

        <?xml version="1.0" encoding="UTF-8"?>
        <beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:aop="http://www.springframework.org/schema/aop"
            xmlns:context="http://www.springframework.org/schema/context"
            xmlns:jee="http://www.springframework.org/schema/jee"
            xmlns:lang="http://www.springframework.org/schema/lang"
            xmlns:p="http://www.springframework.org/schema/p"
            xmlns:tx="http://www.springframework.org/schema/tx"
            xmlns:util="http://www.springframework.org/schema/util"
            xmlns:mvc="http://www.springframework.org/schema/mvc"
            xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
                http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
                http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
                http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
        
             .... some bean configuration
        
            <bean id="propertyConfigurer" 
                  class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
                  p:location="file:web/WEB-INF/jdbc.properties"/>
        
        
            <bean id="dataSource"
                  class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
                  p:driverClassName="${jdbc.driverClassName}"
                  p:url="${jdbc.databaseurl}"
                  p:username="${jdbc.username}"
                  p:password="${jdbc.password}"/>
        
            <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
                <property name="dataSource" ref="dataSource"/>
                <property name="configLocation" value="classpath:hibernate.cfg.xml"/>
                <property name="hibernateProperties">
                    <props>
                        <prop key="hibernate.dialect">${jdbc.dialect}</prop>
                        <prop key="hibernate.show_sql">true</prop>
                        <prop key="hibernate.hbm2ddl.auto">update</prop>
                    </props>
                </property>
             </bean>
        
             <!-- DAO'S -->
             <bean id="blogspotDAO" class="package.BlogspotDAOImpl"/>
        
             <!-- SERVICES -->
             <bean id="blogspotService" class="package.BlogspotServiceImpl"/>
        
             <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
                <property name="sessionFactory" ref="sessionFactory"/>
             </bean>
        
        
             <tx:annotation-driven transaction-manager="transactionManager"/>
        </beans>
        

        我的 jdbc-test.properties 文件

        jdbc.driverClassName=com.mysql.jdbc.Driver
        jdbc.dialect=org.hibernate.dialect.MySQL5Dialect
        jdbc.databaseurl=jdbc:mysql://127.0.0.1:3306/dbspringminiblogtest
        jdbc.username=root
        jdbc.password=
        

        对于hibernate.cfg.xml

        <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE hibernate-configuration PUBLIC
            "-//Hibernate/Hibernate Configuration DTD//EN"
            "http://www.hibernate.org/dtd//hibernate-configuration-3.0.dtd">
        
            <hibernate-configuration>
                <session-factory>
                    <mapping class="somePackage.entity.Author"/>
                    <!-- Other Entity Class to be mapped -->
        
                </session-factory>
            </hibernate-configuration>
        

        我为我创建了 BaseClass 以减少创建多个 @SpringApplicationContext 注释,它也用于配置测试其他类所需的通用配置,只需扩展它。

        @SpringApplicationContext({"file:web/WEB-INF/blogspot-servlet-test.xml"})
        public class BaseServiceTest extends UnitilsJUnit4 {
        }
        

        我使用@SpringApplicationContext 在我的 BaseClass 上加载数据源和其他 bean 配置,这就是我实现它的方式。

        以下:见Spring-Unitils Tutorial 了解更多

        public class BlogspotServiceTest extends BaseServiceTest{
        
            @Mock
            @InjectInto(property = "blogspotDAO")
            @SpringBean("blogspotDAO")
            private BlogspotDAO blogspotDAOMock;
        
            @TestedObject
            @SpringBean("blogspotService")
            private BlogspotService blogspotServiceMock;
        
            @Test
            public void testAddBlogSpot() {
                assertNotNull("BlogspotService Not null",blogspotServiceMock);
            }
        }
        

        注意:请在 TestPackage 中创建 unitils.properties 和 unitils-local.properties 以便能够运行程序。

        @SpringBean 解释和其他注释请阅读:

        Unitils-EasyMock

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-01-19
          • 2016-02-02
          • 1970-01-01
          • 2021-02-27
          • 2020-03-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多