`
jiagyao
  • 浏览: 99311 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

spring中的单元测试的策略

阅读更多
本文主要介绍使用spring提供的对junit的扩展机制来进行单元测试,没有设计mock方面的测试。

一、Spring提供的JUnit框架扩展:

AbstractSpringContextTests:spring中使用spring上下文测试的Junit扩展类,我们一般不会使用这个类来进行单元测试,它是spring内部设计使用到的类
AbstractDependencyInjectionSpringContextTests:这是AbstractSpringContextTests的直接子类,支持依赖spring上下文的测试类,这个类不支持事务。
AbstractTransactionalSpringContextTests:这是AbstractDependencyInjectionSpringContextTests的直接子类,这个类一般应用在事务相关的测试中,一旦完成每个测试它就会正常地回滚事务,不会真正更新数据库,若要手动设置事务相关操作,你可以重载onSetUpInTransaction和onTearDownInTransaction方法,以便手工开始并提交事务,或者调用setComplete()方法。这个类也可以在没有事务的情况下,使用这个类。
AbstractTransactionalDataSourceSpringContextTests:这是AbstractTransactionalSpringContextTests的直接子类,它使用了Spring的基于JDBC的jdbcTemplate工具类,支持数据库级别的事务。
我是按照继承顺序介绍上面四个类的,具体可以参考spring的api文档,或者可以阅读spring的源代码,很简单的代码。

二、测试策略:

下面用一个真实项目的简化版本来作例子,测试的具体目录路径:

test
    --system
        --dao
            --UserDAOImplTest.java
            ......
        --service
            --UserServiceImplTest.java
            ......
        --AbstractSystemTest.java
        --testSystemContext.xml
    --manage
        --dao
            --CustomerDAOImplTest.java
            ......
        --service
            --CustomerServiceImplTest.java
            ......
        --AbstractManageTest.java
        --testSystemContext.xml
    --testApplicationContext.xml
解释:
test是测试路径,system与manage是模块名(这本来是package的路径,为了简化,我就把前面的包名删除了),每个模块中有一个spring的配置文件(我的spring配置文件的命名策略是test+模块名+Context),一个模块级别测试基类(主要是载入spring配置文件,每个该模块的单元测试类都继承该类),然后是分层路径,这里是DAO和service层,包括所有的DAO与service单元测试类,我们还有一个总的spring配置文件testApplicationContext.xml。再多的解释,也不如代码最明显,下面是部分示例代码
testApplicationContext.xml
    <bean id="propertyConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>jdbc.properties</value>
            </list>
        </property>
    </bean>

    <bean id="dataSource"
        class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName">
            <value>${jdbc.driverClassName}</value>
        </property>
        <property name="url">
            <value>${jdbc.url}</value>
        </property>
        <property name="username">
            <value>${jdbc.username}</value>
        </property>
        <property name="password">
            <value>${jdbc.password}</value>
        </property>
    </bean>

    <bean id="parentSessionFactory" abstract="true"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">
                    org.hibernate.dialect.Oracle9Dialect
                </prop>
                <prop key="hibernate.cache.provider_class">
                    org.hibernate.cache.EhCacheProvider
                </prop>
                <prop key="hibernate.max_fetch_depth">3</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.cglib.use_reflection_optimizer">
                    true
                </prop>
            </props>
        </property>
        <property name="dataSource">
            <ref local="dataSource" />
        </property>
    </bean>

    <!-- transaction -->
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <bean id="baseTransactionProxy"
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
        abstract="true">
        <property name="transactionManager" ref="transactionManager" />
        <property name="transactionAttributes">
            <props>
                <prop key="*">
                    PROPAGATION_REQUIRED, -ApplicationException
                </prop>
                <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="list*">PROPAGATION_REQUIRED,readOnly</prop>
            </props>
        </property>
    </bean>

    <!-- Base DAO -->
    <bean id="baseDAO" abstract="true"
        class="com.mycompany.myproject.framework.BaseDAOImpl">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

所有的spring的基本配置文件都放在这里面,我巧妙的把利用spring提供的配置技巧声明了一个抽象的parentSessionFactory,然后让每个子模块的sessionFactory都继承这个对象,这样就减少了不少重复的配置文件

testSystemContext.xml
    <bean id="sessionFactory" parent="parentSessionFactory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="mappingDirectoryLocations">
            <list>
                <value>
                    com/mycompany/myproject/domain/system/maps
                </value>
            </list>
        </property>
    </bean>
   
    <!-- DAO -->
    <bean id="userDAO" parent="baseDAO"
        class="com.mycompany.myproject.module.system.dao.UserDAOImpl">
        <constructor-arg>
            <value>com.mycompany.myproject.domain.system.User</value>
        </constructor-arg>
    </bean>

    <!-- Service -->
    <bean id="userService" parent="baseTransactionProxy">
        <property name="target">
            <bean
                class="com.mycompany.myproject.module.system.service.UserServiceImpl">
                <property name="userDAO" ref="userDAO" />
            </bean>
        </property>
    </bean>

在这个文件中,声明了一个继承parentSessionFactory的sessionFactory,只需配置mappingDirectoryLocations

AbstractSystemTest.java
public abstract class AbstractSystemTest extends
        AbstractTransactionalDataSourceSpringContextTests ...{

    protected String[] getConfigLocations() ...{
        String[] config = new String[] ...{ "testApplicationContext.xml",
                "system/testSystemContext.xml" };
        return config;
    }

}
覆盖基类的方法,提供寻找配置文件的功能,自己可以根据情况把基类改为AbstractTransactionalSpringContextTests

UserDAOImplTest.java
public class UserDAOImplTest extends AbstractSystemTest ...{

    public UserDAO getUserDAO() ...{
        return (UserDAO) applicationContext.getBean("userDAO");
    }

    public void testLoadObject() ...{
        User user = (User) this.getUserDAO().find("01");

        assertNull(user);
    }
}
UserServiceImplTest.java
public class UserServiceImplTest extends AbstractSystemTest ...{

    public UserService getUserService() ...{
        return (UserService) applicationContext.getBean("userService");
    }

    public void testLoadUser() ...{
        User user = (User) this.getUserService().find("01");

        assertNull(user);
    }
}

我的基本策略,就是让让每个开发人员写的单元测试之间不会相互干扰,其实,在spring中的关键问题时把载入context配置文件相互不干扰。上面的示例表明,采用spring提供的配置文件可以轻松达到这个目的
但是,到了项目中后期的时候,会发现service经常需要访问不属于自己模块的DAO,或者是domain对象的关联被映射在hibernate配置文件中,这时会发现这个方式很耗时,因为你需要导入别的模块的配置文件,这时可以采用一个sessionFacotry的配置,而且这时domain对象也很稳定了,不会经常出现
unmmaped class的异常。



本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wangjian5748/archive/2006/09/09/1199549.aspx
分享到:
评论

相关推荐

    07. Spring Boot单元测试

    总结,Spring Boot的单元测试涵盖多个层次,从简单的类方法测试到复杂的集成测试,都有相应的工具和策略。理解和熟练运用这些知识点,能有效提升开发效率,保证代码质量。在实际项目中,应根据需求选择合适的测试...

    spring MVC junit 单元测试(controller)

    在Spring MVC框架中,单元测试是确保代码质量的重要步骤,特别是在控制器层(Controller)。这篇博客主要探讨了如何使用JUnit进行Spring MVC Controller的单元测试。在实际开发中,单元测试可以帮助我们尽早发现潜在...

    spring单元测试

    接下来,我们关注Spring单元测试的实施。在Spring中,我们可以使用`@RunWith(SpringRunner.class)`和`@SpringBootTest`注解来启动一个完整的Spring应用上下文,以便测试Controller层。例如,对于一个名为`...

    spring security测试

    总的来说,对Spring Security进行单元测试是一个细致的过程,涉及到模拟用户、构造请求、验证安全策略以及测试关键组件。通过这种方式,我们可以确保应用的安全性不会因为错误的配置或逻辑而在生产环境中受到威胁。

    Spring对于业务层的单元测试支持

    总的来说,Spring为Java开发者提供了全方位的测试支持,从单元测试到集成测试,再到端到端测试,都有对应的工具和策略。通过有效利用这些特性,我们可以确保业务层代码的质量,降低缺陷率,提高软件的可靠性。在实践...

    Junit 单元测试完整案例

    在案例中,你将看到如何创建测试类,定义测试方法,设置测试数据,以及如何利用JUnit和Spring/Struts提供的工具来编写高效的单元测试。通过分析和运行源码,你可以了解如何将这些概念应用于实际项目,提高代码质量。...

    主题:在Spring中结合Dbunit对Dao进行集成单元测试

    在Spring框架中,进行Dao层的集成单元测试时,常常会结合Dbunit工具来实现数据库相关的测试。Dbunit是一款强大的Java库,它扩展了JUnit,为数据库提供了结构化数据的导入和导出,使得测试更加方便和可靠。下面将详细...

    单元测试案例junit +spring mvc +springboot

    4. 单元测试策略 - 针对Service层:测试业务逻辑,通常会模拟Repository层,避免数据库操作。 - 针对Controller层:使用MockMvc模拟HTTP请求,测试控制器方法的响应,验证模型数据是否正确绑定及返回的视图名。 -...

    Spring、Spring Boot和TestNG测试指南1

    Spring框架提供了全面的测试支持,包括单元测试和集成测试。Spring Testing模块包含了一系列的API和注解,如`@RunWith(SpringRunner.class)`,`@SpringBootTest`,`@WebMvcTest`等,用于简化Spring应用的测试。这些...

    一个项目中的测试策略,指导项目测试

    测试策略是指在软件开发项目中,为了确保软件质量,所采取的一系列测试活动。测试策略的目的是为了确保软件满足业务需求,达到预期的质量目标。测试策略通常包括测试对象、测试类型、测试方法、测试阶段、测试工具等...

    dubbo单元测试maven项目

    【标题】"dubbo单元测试maven项目"指的是在基于Maven构建的Java项目中,对采用Dubbo框架实现的服务进行单元测试的过程。Dubbo是一个高性能、轻量级的开源Java RPC框架,它提供了服务治理功能,包括服务注册、服务...

    rabbitMq与spring、springmvc结合的测试工程

    在IT行业中,消息队列(Message Queue)是一种重要的...以上就是关于“rabbitMq与spring、springmvc结合的测试工程”涉及的主要知识点。在实际开发中,通过这些技术,我们可以构建出高效、稳定、可扩展的分布式系统。

    OAuth2.0单元测试解决方案.docx

    在 OAuth2.0 系统中进行单元测试时,主要难点在于接口测试对 UPMS 的依赖以及 spring-security-test 模块缺乏相关的标准实现。为了解决这些问题,可以采用以下策略: 1. **使用模拟(Mock)技术**:参考 `@...

    Spring5中文文档

    这部分也涵盖了Spring框架下的测试策略,包括DAO和JDBC测试支持。 数据访问章节涵盖了使用Spring JDBC框架进行数据访问的技术,包括数据库连接管理、批量操作、异常处理机制以及内嵌数据库支持。 ORM和数据访问...

    quartz和spring整合完整测试

    此外,还可以使用Spring的AOP特性,配合Quartz实现更灵活的任务调度策略。 下载提供的"quartzSpring"压缩包文件,你可以找到示例代码和配置,进一步学习如何在实际项目中实现Quartz和Spring的整合。如果有任何问题...

    spring5.0.2中文官网文档

    文档中涵盖了如何进行Spring应用的测试策略,包括模拟对象、测试上下文配置以及端到端测试。 在安全领域,Spring Security是不可或缺的一部分。Spring 5.0.2的文档详细讲解了如何配置和使用Spring Security,包括...

    Spring相关测试4

    6. 单元测试:编写单元测试,覆盖所有DAO方法,确保代码质量。 总之,“Spring相关测试4”涵盖了Spring与Hibernate集成的关键方面,尤其是在不同版本下的使用体验。理解这些测试结果将有助于我们选择最适合项目需求...

    spring-boot-test示例程序

    综上所述,"spring-boot-test"示例程序涵盖了Spring Boot中测试的核心概念,包括Rest Controller的集成测试、单元测试的策略以及测试工具的使用,这些都是保证软件质量和可维护性的重要组成部分。通过学习和实践这些...

Global site tag (gtag.js) - Google Analytics