Java 无法从junit测试中的应用程序上下文加载bean

Java 无法从junit测试中的应用程序上下文加载bean,java,spring,spring-mvc,junit,mockito,Java,Spring,Spring Mvc,Junit,Mockito,我正在尝试为我的应用程序实施一组测试。在本例中,我有一些mybatis映射器,它们的bean在applicationContext.xml中定义。例如: <bean id="usersMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="mapperInterface" value="com.myapp.dao.UserMapper" /> <prop

我正在尝试为我的应用程序实施一组测试。在本例中,我有一些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> 
启动期间没有错误。当我尝试获取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>
这是我的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>

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

使用模拟对象时,需要为将要调用的方法提供模拟实现。
getUsers()
方法返回null,因为您尚未设置所需的结果。您可以在mockito网站上查看示例

试试看

@ContextConfiguration(locations = {"classpath:/applicationContext.xml"})
更新
事实上,这也不起作用,因为。applicationContext.xml不在类路径上。需要将其移动到WEB-INF/classes目录中。

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

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


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

Hi@Priyesh。你的第一个解决方案和第二个解决方案都不适合我。第一个抛出“类路径资源[main/webapp/WEB-INF/applicationContext.xml]无法打开,因为它不存在”,第二个抛出,但在我尝试执行context.getBean(“usersMapper”)时启动。。“未定义名为‘usersMapper’的bean”您是否检查过类路径中是否有任何其他applicationContext.xml?您使用的某个库中可能有applicationContext.xml。那可能就是正在加载的那个。你是如何运行测试的?来自IDE或maven/ant?我已经检查过了。我正在从Eclipse运行测试,我的意图是部署war,也通过Maven运行测试。一篇关于这如何帮助OP的简短文本将很有帮助。@Peter hart答案是对问题的更完整的回答Hi Peter。在WEB-INF中放置applicationContext.xml是否错误?将其包含在src/main/resources中是最佳实践吗?我编辑了我的第一篇文章。它似乎可以工作,但我在加载jndi资源时遇到了问题。我认为这本身并没有错。我没有资格谈论Spring的最佳实践,但对于web应用程序来说,在web-INF下的某个地方看到applicationContext.xml并不少见,尽管我很少直接在web-INF下看到它。我不确定如何解决JNDI问题—在我们的环境中,我们通常将数据源定义放在一个单独的导入文件中,并为测试代码引入一个不同的(嵌入式数据库数据源)。您是否尝试了上面Priyesh的建议?如果您想在测试期间使用jndi资源,请在类路径中包含jndi.properties文件,并在此文件中包含上下文信息。e、 例如,
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory java.naming.provider.url=jnp://localhost:1099
。属性的值将根据数据源所在的应用程序服务器而更改。也可以将这些设置为系统属性。或者,您可以直接连接到数据库而不是数据源。如果数据源定义及其属性jndiName仍然存在。。。如何将您建议的文件与数据源链接?我认为您提出的是类似于jdbc.properties的内容,您可以在applicationContext的数据源中读取这些属性。还有一个问题。。。如何区分测试环境和部署之间的applicationContext?也许我需要两个?当您使用jndi名称指定数据源时,spring会在内部尝试创建一个初始上下文来查找jndi资源。为了创建初始上下文,属性abve是必需的,因为它们告诉应用程序jndi资源的注册位置。这些属性可以指定为系统属性(例如-Djava.naming.factory.initial=org.jnp.interfaces.NamingContextFactory),也可以放在类路径中的jndi.properties文件中。至于applicationContext,您可以有一个单独的文件进行测试。你必须做出决定
<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>
@ContextConfiguration(locations = {"classpath:/applicationContext.xml"})