【问题标题】:Spring PropertySource not working in JUnit TestSpring PropertySource 在 JUnit 测试中不起作用
【发布时间】:2015-05-17 17:32:59
【问题描述】:

我在运行 JUnit 测试用例时遇到问题。

问题是, 当我将应用程序作为 Web 应用程序运行时,@PropertySource 通过注入 xml 文件中的所有属性可以正常工作,但是当我将应用程序作为 JUnit 运行时,出现“无法解析占位符”的错误。

web.xml

<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:resources/applicationContext.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:resources/spring-mvc-context.xml</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

DAO 类

@Configuration
@PropertySource("classpath:resources/shore-dal_queries.xml")
public class SpringShoreDao extends SpringBaseDao implements ShoreDao {

    @Value("${shore.getAllShores}")
    private String getShoresQuery;

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }

    @Override
    public Optional<List<Shore>> getAllShores() throws DataAccessException {
        Optional<List<Shore>> shoreList = null;
        try {
            List<Shore> tempList = (getNamedParameterJdbcTemplate().query(getShoresQuery, new ShoreRowMapper()));
            shoreList = Optional.of(tempList);
        }
        catch (org.springframework.dao.DataAccessException e) {
        }
        return shoreList;
    }
}

XML 文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
    <entry key="shore.getAllShores">
        <![CDATA[
            SELECT shoreID, shoreName, isActive, updatedBy, updatedDate, createdBy, createdDate
            FROM shore
        ]]>
    </entry>
</properties>

JUnit 测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
        "classpath:resources/applicationContext.xml",
        "classpath:resources/spring-mvc-context.xml"})
public class SpringShoreDaoTest {


    @Autowired
    ShoreDao shoreDao; 

    @Test
    public void testGetAllShores() throws DataAccessException {
        List<Shore> listShore= shoreDao.getAllShores();
        ............  
    }
}

spring-mvc-context.xml

  <annotation-driven />
    <context:annotation-config />
    <context:component-scan base-package="com.abc.him.utmc" />     
    <resources mapping="/resources/**" location="/resources/" />

    <beans:bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <beans:property name="messageConverters">
            <beans:list>
                <beans:ref bean="jsonMessageConverter"/>
            </beans:list>
        </beans:property>
    </beans:bean>

    <beans:bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    </beans:bean> 

applicationContext.xml

<context:annotation-config />
<context:property-placeholder location="classpath:resources/db.properties"/>
... DB related beans

当我运行 JUnit 测试文件时,我得到了异常,

Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'shore.getAllShores' in string value "${shore.getAllShores}"

当我运行与 Web 应用程序相同的项目时,一切正常。

【问题讨论】:

  • 我看不出您的测试与您发布的其他文件有何关联。你为什么发布 web.xml? applicationContext.xmlspring-mvc-context.xml 这两个是什么?
  • 也添加了这 2 个文件。我不明白为什么 JUnit 在加载该类时无法自动装配字段

标签: java spring jakarta-ee junit spring-4


【解决方案1】:

您可以在测试配置中定义PropertySourcesPlaceholderConfigurer 并将您的resources/shore-dal_queries.xml 设置为它的资源(有一个很好的例子here)。

所以试试这样的:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class SpringShoreDaoTest {

    @Configuration
    @ImportResource({"classpath:resources/applicationContext.xml",
    "classpath:resources/spring-mvc-context.xml"})   
    static class someConfig {

        // because @PropertySource doesnt work in annotation only land
        @Bean
        public static PropertyPlaceholderConfigurer propConfig() {
            PropertyPlaceholderConfigurer ppc =  new PropertyPlaceholderConfigurer();
            ppc.setLocation(new ClassPathResource("resources/shore-dal_queries.xml"));
            return ppc;
        }

        @Bean
        public SpringShoreDao springShoreDao() {
            //probably you do not need this bean since you have component scan in applicationContext 
            return new SpringShoreDao();
        }
    }


    @Autowired
    SpringShoreDao springShoreDao; 

    @Test
    public void testGetAllShores() throws DataAccessException {
        List<Shore> listShore= shoreDao.getAllShores();
        ............  
    }
}

【讨论】:

  • 我已经删除了applicationContext.xmlspring-mvc-context.xml,因为我没有看到它们是如何单独连接到 dao 类以及为什么需要它们。如果您需要它们而不是在仅测试 xml 中定义 PropertyPlaceholderConfigurer 并在两个 xml 资源之后将其添加到 @ContextConfiguration
  • 我需要它,因为 db 配置存在于 applicationContext.xml 中,并且相同的 DAO 类用于获取数据。您能否通过包含该文件来修改代码 sn-p,因为我没有得到“仅测试 xml”
  • 你可以试试@ImportResource这里建议stackoverflow.com/questions/19365366/…
  • 我试过你提到的但仍然存在错误。在示例链接中,它必须在测试类中注入值,但我不想在测试类中注入。为什么@PropertySource 在测试用例执行中不起作用。
  • 它不适用于@ImportResource。我似乎遗漏了一些明显的东西。
猜你喜欢
  • 2012-05-29
  • 1970-01-01
  • 2018-12-01
  • 2012-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-07
相关资源
最近更新 更多