【问题标题】:How to Autowire in Junit Tests (General Newb Enquiry)如何在 Junit 测试中自动装配(一般 Newb 查询)
【发布时间】:2014-04-09 20:01:53
【问题描述】:

这是一个关于 Spring 和创建应用程序上下文的一般问题。

我正在为网站应用程序进行单元测试。该网站使用 Spring 和 Hibernate,我想使用数据库中的一些数据进行测试。我不知道如何将 Spring IOC 容器连接到我的单元测试。我知道 applicationContext.xml 的位置,但是如何在单元测试中访问它的 bean?

这是我的代码:

package com.example.test;

import junit.framework.Assert;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

public class SessionFactoryTest {

    @Autowired
    SessionFactory sessionFactory;

    @Test
    public void testSessionFactoryAutowiring() {
         Session session = sessionFactory.getCurrentSession();
         Assert.assertEquals(session.getClass(),Session.class);
    }
}

哪个会产生错误

Testsuite: com.example.test.SessionFactoryTest
Tests run: 1, Failures: 0, Errors: 1, Time elapsed: 0.011 sec

Testcase: testSessionFactoryAutowiring took 0.002 sec
Caused an ERROR
null
java.lang.NullPointerException
at com.example.test.SessionFactoryTest.testSessionFactoryAutowiring(SessionFactoryTest.java:19)

现在我的问题是,如何从普通的 applicationContex.xml 访问 sessionFactory?如何访问容器?我不介意创建自己的,但是到今天结束时,我真的很想编写单元测试。谁不会?

更新:我确实根据 Spring 文档将注释添加到我的测试类中

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})

但是找不到文件,我不知道如何指定与我的测试相关的文件。

Testsuite: com.example.test.SessionFactoryTest
Tests run: 1, Failures: 0, Errors: 1, Time elapsed: 0.045 sec

Testcase: testSessionFactoryAutowiring took 0.035 sec
Caused an ERROR
Failed to load ApplicationContext
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:308)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:220)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:301)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:303)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [applicationContext.xml]; nested exception is java.io.FileNotFoundException: class path resource [applicationContext.xml] cannot be opened because it does not exist
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:341)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:143)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:178)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:149)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:212)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:81)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1)
at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:280)
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:304)
Caused by: java.io.FileNotFoundException: class path resource [applicationContext.xml] cannot be opened because it does not exist
at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:158)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:328)

我的项目结构如下:

src/
web/WEB-INF/applicationContext.xml
test/java/com/example/SessionFactoryTest.java

并且是用 ant 构建的。

【问题讨论】:

    标签: java spring hibernate unit-testing junit


    【解决方案1】:

    在位置中使用类路径将不起作用,因为您没有使用 applicationContext.xml 的默认位置

    但这可能会奏效。

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = { "src/stuff web/WEB-INF/applicationContext.xml" })
    public class SessionFactoryTest {
    

    我想你的应用程序上下文文件中也有这个:

    <context:component-scan base-package="com.example" />
    
    <bean id="sessionFactory" class="com.example.SessionFactoryImpl" />
    

    【讨论】:

    • 我确实以@ContextConfiguration(locations = {"web/WEB-INF/applicationContext.xml"}) 的形式尝试过,但没有成功。
    • 我能够在 ant 中为测试执行范围设置类路径。但我仍然无法实例化 bean。想法?
    • 能否请您粘贴您的应用程序上下文的样子?
    【解决方案2】:

    您需要声明一个弹簧测试上下文并使用@Runwith 进行注释。 xml 来到 src/test/resources/my-test-config.xml

    @RunWith(SpringJunit4ClassRunner.class)
    @ContextConfiguration(locations = { "classpath:my-test-config.xml"})
    public class myTest { ...
    

    编辑:我不确定,但我想您也需要将休眠 jar 添加到测试范围内的类路径中

    【讨论】:

    • 你能改写一下“xml来了”吗?我很难解析。
    • “通常”的项目结构如下所示
    • 对不起,这对我来说仍然没有意义,我试图弄清楚如何在 @ContextConfiguration(locations = {}) 注释中指定 applicationContext.xml 的位置。你能解释一下怎么做吗?
    • 您的项目中需要一个 testresource 文件夹。按照惯例,您将单元测试中需要的文件放在 src/test/resources 中,将单元测试放在 src/test/java 中
    • 你是用 maven 构建的吗?
    【解决方案3】:

    对于您的示例代码,您应该在会话工厂单元测试中测试 SessionFactory 的返回值。

    如果您想在单元测试中注入依赖项,请考虑使用 MockitoAnnotations 之类的工具自动将模拟对象注入到您的测试类中

    【讨论】:

      【解决方案4】:

      我将类路径设置为在我的 ant build.xml 中包含 web 目录,现在找到了 applicationContext.xml。现在我还有其他问题。特别是主 applicationContext.xml 中的 jndi 引用。总而言之,这就是最终的蚂蚁任务

      <target name="test-platform" depends="compile_tests">
          <mkdir dir="${platform.test.log.dir}"/>
          <junit fork="true" haltonerror="true">
              <classpath refid="test.build.classpath"/>
              <classpath location="test"/>
              <classpath location="${build_testclassdir}"/>
              <batchtest todir="${platform.test.log.dir}">
                  <formatter type="plain" usefile="true"/>
                  <fileset dir="${javatests}">
                      <include name="**/*Test.java"/>
                  </fileset>
              </batchtest>
          </junit>
      </target>
      

      然后在我的一个测试中

      @Transactional
      @RunWith(SpringJUnit4ClassRunner.class)
      @ContextConfiguration(locations = {"classpath:resources/test-applicationContext.xml"})
      

      并在 test/resources 目录中放置了一个测试上下文

      [david@david web]$ ll test/resources/test-applicationContext.xml 
      -rw-rw-r-- 1 david david 4851 Apr  9 16:02 test/resources/test-applicationContext.xml
      

      【讨论】:

      • 编辑您的帖子并包含问题和应用程序上下文内容。顺便说一句,单元测试不应该有任何依赖关系,因此你应该模拟依赖关系。您可以为此目的使用 EasyMock。您正在尝试进行集成测试。
      • Henrik,好点子。我需要编写的测试是专门针对数据库中某个表中所有现有的真实数据测试某个方法的行为。
      • 您遇到了哪些错误?和应用上下文内容?
      • Henrik,感谢您的回复。现在一切正常,(我的 CTO 很高兴,这很酷)。正如我在答案中提到的,这是一条评论,我基本上需要做 3 件事,1. 创建一个 ant 目标并设置类路径以包含测试目录。 2. 在测试类上添加 Transaction、RunWith 和 ContextConfiguration 注解,位置指向 test-applicationContext.xml。 3. 在应用程序上下文中设置一个 org.apache.commons.dbcp.BasicDataSource 以不依赖 jndi。最后,这让我可以在我的测试类中自动装配一个 sessionFactory,这就是目标。是的
      猜你喜欢
      • 2015-02-19
      • 2012-05-20
      • 1970-01-01
      • 1970-01-01
      • 2011-04-09
      • 2018-03-07
      • 1970-01-01
      • 1970-01-01
      • 2014-03-11
      相关资源
      最近更新 更多