Unitils:如何从Spring获取数据库属性

发布于 2025-01-07 22:28:49 字数 375 浏览 0 评论 0原文

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

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

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

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

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

谢谢, 阿迪

I am using Unitils with Spring for unit testing. I've configured Spring with datasource using a properties file.

My question is how can I use the same datasource or the same properties for Unitils?

Unitils expects a file in the classpath unitils.properties with database configuration parameters like url, user, password and driver.

I've tried to configure Unitils using the properties used in the Spring configuration as below but it is not working.

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

Thanks,
Adi

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

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

发布评论

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

评论(3

风尘浪孓 2025-01-14 22:28:49

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

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

例如

@SpringApplicationContext({" CorrectDataSourceContext.xml"})

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

One potential solution... You could have your Spring configuration read its datasource parameters from the unitils.properties, instead of the other way around. Probably not ideal.

I believe unitils is using spring under the covers, so you might also try adding your datasource context in your unitils tests by using @SpringApplicationContext. If you could figure out the name of the datasource bean setup by unitils when it starts up, you could override it in your context (assuming the unitils datasource bean is created before the other spring beans are which may/may not be true.)

e.g.

@SpringApplicationContext({"correctDataSourceContext.xml"})

EDIT: Another option that will definitely work: https://stackoverflow.com/a/6561782/411229
Basically instantiate Unitils yourself and set the properties manually.

一桥轻雨一伞开 2025-01-14 22:28:49

瑞安的回答是正确的,也很有帮助,尽管我使用了不同的方法。

我扩展了类 PropertiesDataSourceFactory 来重写方法,如下所示:

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

Ryan answer is correct and helpful as well though I've used different approach.

I extended the class PropertiesDataSourceFactory ro override the methods as follows:

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;
    }

}

and also wrote a SystemPropertiesReader as:

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;
    }

}

and added a bean with the properties file:

<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>

add the following to unitils.properties:

org.unitils.database.config.DataSourceFactory.implClassName=x.y.UnitilsDataSourceFactory
睫毛溺水了 2025-01-14 22:28:49

只是想添加一些想法,我不确定这是否是最佳实践,或者如果有问题请不要纠正我。

  • 我的项目

    -src

    --测试包

    ---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-Uni​​tils 教程
有关更多详细信息

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

Just want to add some idea and im not sure if it is a best practice or not so correct me if theres something wrong.

  • MYPROJECT

    -src

    --TestPackage

    ---BaseServiceTest.class

    ---BlogspotServiceTest.class

    --hibernate.cfg.xml

    -web

    --WEB-INF

    ---blogspot-servlet-test.xml

    ---jdbc-test.properties

in my case I used my blogspot-servlet-test.xml to call or to create the datasource

<?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>

MY jdbc-test.properties file

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=

For 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>

and i created BaseClass for me to lessen creating of multiple @SpringApplicationContext annotation and it is also use to configure common configuration needed in testing other class, just extends it.

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

i used @SpringApplicationContext to load the datasource and other bean configurations on my BaseClass and this is how i implement it.

Below : see Spring-Unitils Tutorial
for more details

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);
    }
}

NOTE: please create unitils.properties and unitils-local.properties inside TestPackage to be able to run the program.

For @SpringBean explanation and other annotation please read :

Unitils-EasyMock

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