【问题标题】:Spring/Hibernate/Junit example of testing DAO against HSQLDB针对 HSQLDB 测试 DAO 的 Spring/Hibernate/Junit 示例
【发布时间】:2011-02-21 03:39:27
【问题描述】:

我正在尝试实现一个 JUnit 测试来检查 DAO 的功能。 (DAO 将创建/读取基本的对象/表关系)。

我遇到的麻烦是 DAO(对于非测试代码)的持久性是通过使用 Spring/Hibernate 的内部解决方案完成的,这消除了通常的 @987654321我发现的大多数示例都包含@templates。

因此,我在理解如何设置 JUnit 测试以实现 DAO 以创建/读取(只是非常基本的功能)到内存中 HSQLDB 时遇到了一些麻烦。我找到了一些示例,但内部持久性的使用意味着我无法扩展示例显示的某些类(我似乎无法正确设置 application-context.xml)。

谁能建议我可以查看的任何项目/示例(或任何文档),以进一步了解实现此测试功能的最佳方法?我觉得这应该很简单,但是在实现我发现的示例时我一直遇到问题。

编辑:

这是我的解决方案以提高可读性,适合任何需要帮助的人:

  • 我的TestClass

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "classpath:applicationContextTest-Example.xml")
    @Transactional
    public class ExampleDaoTest extends AbstractTransactionalJUnit4SpringContextTests {
        @Resource(name = "sessionFactory")
        private SessionFactory exampleSessionFactory;
    
        @Resource(name = "exampleDao")
        private ExampleDao exampleDao;
    
  • 我的applicationContext.xml 文件:

    <!-- List of Daos to be tested -->
    <bean id="exampleDao" class="org.myExample.ExampleDao"/>
    
    <!-- Datasource -->
    <bean id="example_dataSource"
          class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
        <property name="url" value="jdbc:hsqldb:mem:ExampleTest"/>
        <property name="username" value="sa"/>
        <property name="password" value=""/>
    </bean>
    
    <!-- Session Factory -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="example_dataSource"/>
        <property name="annotatedClasses">
            <list>
                <value>org.myExample.ExampleClass</value>
            </list>
        </property>
        <property name="hibernateProperties">
            .... left to user to choose properties
        </property>
    </bean>
    

【问题讨论】:

  • 一些附加信息:我对 Spring/Hibernate 的配置不太熟悉,直到现在我已经在以前的项目中配置了它们。我当前的项目是配置的混搭,我无法弄清楚我所指的“内部”类是如何获得其会话工厂的。所有的 DAO 都对其进行了扩展(一个抽象类),其中包含一个抽象声明: public abstract SessionFactory getSessionFactory();我无法弄清楚“getSessionFactory()”方法的来源。我认为它必须以某种方式由 Spring 注入,但我找不到任何这样做的配置文件。
  • 谢谢大家,你们都很有帮助。对于未来的人:我将我的 applicationContext-Test.xml 文件包含在我的单元测试中(通过 Willie 指定的 @ContextConfiguration)我在其中定义了 HSQLDB 数据源、会话工厂、事务管理器和作为 beans 。我的测试类注释为:@RunWith(SpringJUnit4ClassRunner.class)、@ContextConfiguration(locations = "your appContext.xml") @Transactional,并且我的会话工厂和 dao 被注释为资源(来自 .xml defs):@Resource( name = "sessionFactory")

标签: java hibernate spring junit hsqldb


【解决方案1】:

我的应用程序上下文看起来有点不同

<beans:bean class="org.apache.commons.dbcp.BasicDataSource" id="HSQL_DS">
    <beans:property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
    <beans:property name="url" value="jdbc:hsqldb:mem:Test"/>
    <beans:property name="username" value="sa"/>
    <beans:property name="password" value=""/>
</beans:bean>
<jdbc:embedded-database id="HSQL_DS">
    <jdbc:script location="classpath:schema.sql"/>
    <jdbc:script location="classpath:data.sql"/>
</jdbc:embedded-database>

我的测试类看起来像这样:

public class Tester {

    private EmbeddedDatabase db;

    @Before
     public void setUp(){
        db = new EmbeddedDatabaseBuilder().addDefaultScripts().build();


    }

    @Test
    public void TestMe(){
        System.out.println("Testing");
    }


    @After
    public void tearDown(){

        db.shutdown();
    }
}

【讨论】:

    【解决方案2】:

    我最近使用 HibernateSpringHSQLDB 在我的一些代码中实现了类似的解决方案。

    值得注意的是 AbstractTransactionalJUnit4SpringContextTests 现在已被弃用 - 但它仍然很容易测试 - 我在这里介绍了大部分细节:http://automateddeveloper.blogspot.com/2011/05/hibernate-spring-testing-dao-layer-with.html

    【讨论】:

      【解决方案3】:

      Spring 3 提供了一个新的 jdbc 命名空间,其中包括对嵌入式数据库(包括 HSQLDB)的支持。这样就可以处理那部分了。

      我想知道“内部解决方案”可能是什么。您可以使用注释(JPA 或 Hibernate 注释)来 ORM 域对象,那么为什么需要“内部解决方案”?例如:

      <bean id="sessionFactory"
          class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
          p:dataSource-ref="dataSource"
          p:packagesToScan="myapp.model" />
      

      就实现测试而言,请使用 Spring 的 TestContext 框架。测试可能看起来像这样(我再次假设下面的 Spring 3,尽管只需将 @Inject 更改为 @Autowired 它应该在 Spring 2.5 中工作):

      @RunWith(SpringJUnit4ClassRunner.class)
      @ContextConfiguration({
          "/beans-datasource-it.xml",
          "/beans-dao.xml",
          "/beans-service.xml",
          "/beans-web.xml" })
      @Transactional
      public class ContactControllerIT {
          @Inject private ContactController controller;
      
          ... setUp() and tearDown() ...
      
          @Test
          public void testGetContact() {
              String viewName = controller.getContact(request, 1L, model);
      
              ... assertions ...
          }
      }
      

      例如,您可以将嵌入式数据库放在beans-datasource-it.xml 中。 (这里的“it”代表集成测试,文件位于类路径中。)此示例中的控制器位于beans-web.xml,并将自动连接到ContactController 字段中。

      这只是一个要做什么的大纲,但希望它足以让你开始。

      【讨论】:

        【解决方案4】:

        See here。它假定 maven2 作为构建工具,但您可以轻松使用任何东西。

        【讨论】:

          【解决方案5】:

          hibernate 的底线是SessionFactory - 您的内部解决方案很可能会以某种方式创建其中之一。找出方法,然后添加一个 bean,以相同的方式在您的测试应用程序上下文中创建一个(或者如果可能,使用在运行时使用的内部代码。)。您可能需要创建自己的 FactoryBean 来进行实例化。 (使用AbstractFactoryBean 作为您的基类。)

          一旦到位,大多数使用 LocalSessionFactoryBean 的示例都可以迁移到您的情况 - 使用您的自定义工厂 bean,而不是使用 LocalsessionFactoryBean。

          (如果您还没有这样做,请查看 spring 参考中的 Testing 部分 - 它使使用 Spring 进行测试,并使用上下文中的 bean 注入测试变得轻而易举。)

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-06-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-01-25
            • 1970-01-01
            • 1970-01-01
            • 2014-12-24
            相关资源
            最近更新 更多