【问题标题】:Unable to load beans from Application Context in junit test无法在junit测试中从应用程序上下文加载bean
【发布时间】:2014-05-12 15:37:53
【问题描述】:

我正在尝试为我的应用实施一组测试。在这种情况下,我有一些 mybatis 映射器,它们的 bean 定义在我的 applicationContext.xml 中。例如:

<bean id="usersMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <property name="mapperInterface" value="com.myapp.dao.UserMapper" />
    <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean> 

我一直在寻找如何正确实施 junit 测试的几个小时,因为一些互联网帖子已被弃用或不是最新的。这实际上是我的junit类:

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


    @Autowired
    ApplicationContext context;

    @Test
    public void testCreateGroup() throws SQLException {
        UserMapper um = (UserMapper)context.getBean("usersMapper");  
    }
}

启动过程中没有错误。当我尝试获取 bean usersMapper 时返回异常(没有 bean 定义..)也许是没有加载正确的 applicationContext?

我也尝试过 Mockito,但没有成功。我读过它做了很酷的事情,但它是否能够像 Spring 一样加载上下文?当我从 UserMapper 调用 getUsers 方法时,它返回 null。这是我的实现:

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


    @Mock
    private UserMapper userMapper;


    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
    }


    @Test
    public void testCreateGroup() throws SQLException {
        userMapper.getUsers(); 
    }
}

记录一下...我的applicationContext.xml放在/src/main/webapp/WEB-INF/applicationContext.xml 希望你能指导我正确的方式。谢谢

Edit1:添加了applicationContext.xml和context.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:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="java:comp/env/jdbc/adminDB"/>
    </bean>

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

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation" value="/WEB-INF/mybatis-config.xml" /> 
    </bean> 

    <bean id="usersMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
        <property name="mapperInterface" value="es.unican.meteo.dao.UserMapper" />
        <property name="sqlSessionFactory" ref="sqlSessionFactory" />
    </bean> 

</beans>

Peter Hart 解决方案似乎加载了 applicationContext.xml,但出现了一个新问题。我需要在我的应用程序中使用 jndi 资源(引用包含在 applicationContext.xml 中)。这在测试环境中不可能吗? 异常显示如下:

Caused by: javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial 

这是我的 context.xml

<Context>
    <Resource name="jdbc/adminDB" auth="Container" type="javax.sql.DataSource"
             maxActive="20" maxIdle="10" username="***" password="***"
             driverClassName="org.apache.derby.jdbc.ClientDriver"
             url="jdbc:***"/>
</Context>

【问题讨论】:

  • 如果您想在测试期间使用 jndi 资源,请在类路径中包含 jndi.properties 文件,并在此文件中包含上下文信息。例如,java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory java.naming.provider.url=jnp://localhost:1099。属性的值将根据数据源所在的应用程序服务器而变化。您也可以将它们设置为系统属性。或者,您可以使用直接连接到数据库而不是数据源。
  • 但是我有一个问题。如果数据源定义的属性 jndiName 仍然存在...如何将您建议的文件与数据源链接?我认为您提出了类似于 jdbc.properties 的内容,您可以在 applicationContext 的数据源中读取这些属性。还有一个问题......我如何区分测试环境和部署之间的 applicationContext ?也许我需要两个?
  • 当你指定一个带有 jndi 名称的数据源时,spring 内部会尝试创建一个 Initial Context 来查找 jndi 资源。要创建初始上下文,上述属性是必需的,因为它们告诉应用程序 jndi 资源在哪里注册。这些属性可以指定为系统属性(例如 -Djava.naming.factory.initial=org.jnp.interfaces.NamingContextFactory),也可以放在类路径中的 jndi.properties 文件中。
  • 至于applicationContext,你可以有一个单独的文件进行测试。您必须通过在类路径中的应用程序(src)之前指定测试上下文文件夹来确保之前读取了测试上下文文件。在 Eclipse 中,您可以使用“项目属性>Java 构建路径”中的“订单和导出”选项卡来执行此操作。

标签: java spring spring-mvc junit mockito


【解决方案1】:

问题是您请求了一个类路径资源,而WEB-INF/applicationContext.xml 可能不在类路径上(通常不会)。

您可以尝试将 applicationContext.xml 移动到类路径上的某个位置。我猜您使用的是 maven,在这种情况下,这通常是 src/main/resources 或 src/test/resources(如果这是特定于特定测试的,而不是“真实的”应用程序上下文文件)。我还会按照@ohiocowboy 的建议修复您的@ContextConfiguration(假设您将其直接放在该目录中,因为如果您明确说明位置,通常情况会更好)。

如果您的应用程序上下文绝对需要在WEB-INF/applicationContext.xml 中,您可以尝试使用file:src/main/webapp/WEB-INF/applicationContext.xml。如果您使用 mvn test 从项目的基本目录运行,它应该可以工作,并且它可能也可以在 eclipse 测试运行程序中工作(不知道 Idea 或 NetBeans,但我猜它可能工作)。

【讨论】:

  • 嗨,彼得。将 applicationContext.xml 放在 WEB-INF 中有错吗?将它包含在 src/main/resources 中是最佳实践吗?我编辑了我的第一篇文章。它似乎有效,但我在加载 jndi 资源时遇到问题。
  • 我认为这本身并没有错。我没有资格谈论 Spring 的最佳实践,但是对于 Web 应用程序,在 WEB-INF 下的某处看到 applicationContext.xml 并不少见,尽管我很少直接在 WEB-INF 下看到它。 JNDI 问题我不知道如何解决 - 在我们的环境中,我们通常将数据源定义放在单独的导入文件中,并为我们的测试代码拉入不同的(嵌入式数据库数据源)。您是否尝试过上面 Priyesh 的建议?
【解决方案2】:

您的应用程序上下文未正确加载。 @ContextConfiguration 注解的位置属性应该是"classpath:main/webapp/WEB-INF/applicationContext.xml"、"classpath:**/applicationContext.xml" 或"classpath*:applicationContext.xml"。运行测试时,应用程序没有部署,因此 WEB-INF 不会在类路径中(除非您自己将其添加到测试类路径中)。

使用模拟对象时,您需要为将要调用的方法提供模拟实现。 getUsers() 方法返回 null,因为您尚未设置所需的结果。您可以在 http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html 查看 mockito 网站的示例。

【讨论】:

  • 嗨@Priyesh。您的第一个解决方案和第二个解决方案都不适合我。第一个抛出“类路径资源 [main/webapp/WEB-INF/applicationContext.xml] 无法打开,因为它不存在”,第二个抛出,但是当我尝试执行 context.getBean("usersMapper") ; ..“没有定义名为'usersMapper'的bean”
  • 你检查过classpath中是否还有其他applicationContext.xml吗?
  • 您使用的某个库中可能有一个 applicationContext.xml。那可能是正在加载的那个。你是如何运行测试的?来自 IDE 或 maven/ant?
  • 我已经检查过了。我正在从 Eclipse 运行测试,我的目的是部署通过 Maven 运行测试的战争。
【解决方案3】:

试试

@ContextConfiguration(locations = {"classpath:/applicationContext.xml"})

更新 实际上这也行不通,因为。 applicationContext.xml 不在类路径中。需要移动到WEB-INF/classes目录下。

【讨论】:

  • 关于这如何帮助 OP 的简短文本会有所帮助。
  • @Peter hart 的回答是对这个问题的更完整的回答
猜你喜欢
  • 2019-01-17
  • 1970-01-01
  • 1970-01-01
  • 2013-02-03
  • 2018-07-11
  • 2013-02-08
  • 2015-04-27
  • 2016-10-31
  • 1970-01-01
相关资源
最近更新 更多