具有@Value 注释的模拟对象

Mock object that has @Value annotation

我有这个 class 存储 webapp 的属性。它在服务 class 中自动装配。我想模拟该服务和 运行 JUnit 测试,但它表明无法自动装配 @Value 字段。

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private myapp.ConfigProperties myapp.SectionServiceImpl.configProperties; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'configProperties': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: public java.lang.String myapp.ConfigProperties.appFileFolderDocument; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'webapp.root' in string value "${webapp.root}documents\"

源代码

@Component
public class ConfigProperties {

    @Value("${email.active}")
    public String emailActive;

    @Value("${app.homepage}")
    public String appHomepage;

    @Value("${app.context}")
    public String appContext;

    @Value("${email.username}")
    public String adminEmailAddress;

    @Value("${account.trial.dates}")
    public int trialVersionDates;

    @Value("${app.file.folder.document}")
    public String appFileFolderDocument;

    @Value("${app.file.folder.pdf}")
    public String appFileFolderPdf;

    @Value("${app.file.folder.logo}")
    public String appFileFolderLogo;

    @Value("${app.section.folder.logo}")
    public String appSectionFolderLogo;

    @Value("${app.folder.img}")
    public String appFolderImage;

    @Value("${email.emailAddressMatthijs}")
    public String emailAddressMatthijs;

    @Value("${email.emailAddressInfo}")
    public String emailAddressInfo; 


    // Pagination
    @Value("${pagination.items_per_page}")
    public int paginationItemsPerPage;  

    @Value("${pagination.num_display_entries}")
    public int paginationNumDisplayEntries; 

    @Value("${pagination.num_edge_entries}")
    public int paginationNumEdgeEntries;    


    @Value("${use.pdf.report.newsolution}")
    public int usePdfReportNewSolution; 

    @Value("${use.pdf.report.numberOfIndicatorInPdfReport}")
    public int usePdfReportNumberOfIndicatorInPdfReport;    


    @Value("${recaptcha.publickey}")
    public String captcharPublicKey;    

    @Value("${recaptcha.privatekey}")
    public String captcharPrivateKey;   


    @Value("${file.upload.not.allowed}")
    public String fileUploadNotAllowed;

    @Value("${file.upload.image}")
    public String fileUploadImage;

    @Value("${maxUploadFileSize}")
    public String maxUploadFileSize;

    // Pagination
    @Value("${pagination.admin.items_per_page}")
    public int paginationAdminItemsPerPage; 

    @Value("${pagination.admin.num_display_entries}")
    public int paginationAdminNumDisplayEntries;    

    @Value("${pagination.admin.num_edge_entries}")
    public int paginationAdminNumEdgeEntries;   

}

我已经尝试在 XML 中创建 bean,但它仍然显示错误。

<bean id="configProperties" class="myapp.ConfigProperties">
    <property name="appFileFolderDocument" value="E:/myapp/src/main/webapp/documents" />
</bean>

错误

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: public java.lang.String myapp.ConfigProperties.appFileFolderDocument; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'webapp.root' in string value "${webapp.root}documents\"

configs.properties

app.context = http://localhost:8080/myapp/
app.homepage = http://localhost:8080/myapp
app.file.folder.document =  ${webapp.root}documents\
app.file.folder.pdf = ${webapp.root}pdf\
app.file.folder.logo = ${webapp.root}companylogo\
app.section.folder.logo = ${webapp.root}logo\
app.folder.img = ${webapp.root}images\

JUnit 测试文件

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:test-context.xml"})
public class IndicatorTemplateDaoTest {

    @Test
    public void test() {

    }
}

测试-context.xml

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xmlns:repository="http://www.springframework.org/schema/data/repository"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans.xsd 
       http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context-2.5.xsd 
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/data/repository
       http://www.springframework.org/schema/data/repository/spring-repository.xsd
       http://www.springframework.org/schema/data/jpa
       http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">

    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:META-INF/properties/config.properties"/>
    </bean>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="maxActive" value="${jdbc.maxactive}"/>
        <property name="initialSize" value="${jdbc.initialsize}"/>
    </bean>

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceXmlLocation" value="classpath*:META-INF/persistence.xml"></property>
        <property name="persistenceUnitName" value="JpaPersistenceUnit" />
        <property name="dataSource" ref="dataSource"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" >
                <property name="showSql" value="false"/>
            </bean>
        </property>
    </bean>

    <bean id="entityManager" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

    <tx:annotation-driven />

    <context:component-scan base-package="myapp.dao.impl" >
    </context:component-scan>

    <bean id="indicatorTemplateDao" class="myapp.dao.impl.IndicatorTemplateDaoImpl">
    </bean>

    <bean id="indicatorTemplateService" class="myapp.service.impl.IndicatorTemplateServiceImpl">
    </bean>

    <bean id="indicatorDao" class="myapp.dao.impl.IndicatorDaoImpl">
    </bean>

    <bean id="indicatorService" class="myapp.service.impl.IndicatorServiceImpl">
    </bean>

    <bean id="indicatorActionDao" class="myapp.dao.impl.IndicatorActionDaoImpl">
    </bean>

    <bean id="menuService" class="myapp.service.impl.MenuServiceImpl">
    </bean>

    <bean id="sectionService" class="myapp.service.impl.SectionServiceImpl">
    </bean>

    <bean id="configProperties" class="myapp.utils.ConfigProperties">
        <property name="appFileFolderDocument" value="E:/myapp/src/main/webapp/documents" />
    </bean>

</beans>

如何解决?

首先,从 Spring Framework 3.1 开始,您不应该使用 PropertyPlaceholderConfigurer。相反,您应该使用 PropertySourcesPlaceholderConfigurer,它支持 属性 源的层次结构。

从 Spring 3.1 开始,<context:property-placeholder ...> XML 命名空间元素在后台自动使用 PropertySourcesPlaceholderConfigurer

所以一旦你切换到 PropertySourcesPlaceholderConfigurer,你可以简单地按照我在这个相关讨论中的说明操作:

此致,

Sam(Spring TestContext Framework 的作者)