简体   繁体   English

Spring单元测试和InitialContext

[英]Spring unit testing and InitialContext

I would like to get a simple integration test with Tomcat and Spring 4 running, injecting a spring component and use my existing data source configuration from Tomcat. 我想获得一个运行Tomcat和Spring 4的简单集成测试,注入一个spring组件,并使用来自Tomcat的现有数据源配置。 I don't want to configure my DataSource twice. 我不想两次配置我的数据源。 Everything, including my data source, is configured in the file WebContent/WEB-INF/application-context.xml . 包括我的数据源在内的所有内容都在文件WebContent/WEB-INF/application-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:task="http://www.springframework.org/schema/task"
    xmlns:util="http://www.springframework.org/schema/util" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
                http://www.springframework.org/schema/data/jpa      http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
        http://www.springframework.org/schema/jee           http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">

    <task:annotation-driven />

    <!-- annotations in bean classes -->
    <!-- context:annotation-config / -->

    <!-- mvc:annotation-driven / -->
    <context:component-scan base-package="com.mycompany.package.**" />

    <jpa:repositories base-package="com.mycompany.package.**" />


    <!-- <aop:aspectj-autoproxy proxy-target-class="true"/> -->

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

    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="persistenceUnitName" value="packagePU" />
        <property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
        <property name="jpaDialect">
            <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect" />
        </property>
        <property name="jpaPropertyMap">
            <props>
                <prop key="eclipselink.weaving">false</prop>
            </props>
        </property>
    </bean>

    <bean id="jpaVendorAdapter"
        class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
        <property name="generateDdl" value="false" />
        <property name="showSql" value="true" />
    </bean>

    <bean id="jpaDialect"
        class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect" />
    <!-- <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> 
        <property name="validationMessageSource" ref="messageSource"/> </bean> -->

    <bean id="messageSource"
        class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basenames" value="i18n/messages" />
    </bean>

    <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/DefaultDB" />

</beans>

I am using this tutorial http://docs.spring.io/spring/docs/current/spring-framework-reference/html/integration-testing.html#testcontext-ctx-management , but I don't fully understand how I can just run my test in the context of Tomcat that provides my DataSource. 我正在使用本教程http://docs.spring.io/spring/docs/current/spring-framework-reference/html/integration-testing.html#testcontext-ctx-management ,但是我不完全了解我可以在提供数据源的Tomcat上下文中运行我的测试。

Currently, I am this far: 目前,我到此为止:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = { "file:WebContent/WEB-INF/application-context.xml"})
public class SimulatorTest {

    @Autowired
    private ShiftSimulator simulator;

    @BeforeClass
    public void setup() {
        // ??? 

    }


    @Test
    public void testShiftStart() {
        System.out.println("Hello world");
    }

}

Currently, I get this error when running the test 目前,在运行测试时出现此错误

java.lang.IllegalStateException: Failed to load ApplicationContext
...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in URL [file:WebContent/WEB-INF/application-context.xml]: Cannot resolve reference to bean 'dataSource' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource': Invocation of init method failed; nested exception is 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
...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource': Invocation of init method failed; nested exception is 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
...
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
...

I fully understand that there needs to be a InitialContext, but how can I provide my test with my context that is provided by Tomcat, including my Data Source configuration? 我完全理解需要有一个InitialContext,但是如何使用Tomcat提供的上下文(包括数据源配置)提供测试? I don't want to set my data source connection credentials twice. 我不想两次设置数据源连接凭据。

Solved it. 解决了。 Just to recap the problem: Spring tries to create the dataSource bean and fails at looking up the JNDI name - because there is no JNDI available. 只是为了解决这个问题:Spring尝试创建dataSource bean,但无法查找JNDI名称-因为没有可用的JNDI。

So what I did for testing, I just created another XML files that overrides the bean dataSource . 因此,为了进行测试,我刚刚创建了另一个XML文件,该文件覆盖了bean的dataSource I ignored the file in version control and ask every developer to copy this file in place: 我忽略了版本控制中的文件,并要求每个开发人员将其复制到位:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    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.0.xsd">

    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource"
        p:driverClassName="com.sap.db.jdbc.Driver"
        p:url="jdbc:sap://xxx:30015"
        p:username="sa"
        p:password="">
    </bean>

</beans>

In the test class, I am providing the additional file reference that overrides dataSource so it never tries to do the failing JNDI lookup: 在测试类中,我提供了覆盖dataSource的其他文件引用,因此它绝不会尝试执行失败的JNDI查找:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = { "file:WebContent/WEB-INF/application-context.xml", "file:WebContent/WEB-INF/test-datasource.xml"  })
public class SimulatorTest {
...

TomcatJNDI offers a comfortable solution for this problem. TomcatJNDI为这个问题提供了一个舒适的解决方案。 It's based on Tomcat's JNDI system and initializes only Tomcat's JNDI environment without starting the server. 它基于Tomcat的JNDI系统,并且仅在不启动服务器的情况下初始化Tomcat的JNDI环境。 So you can access all your resources as configured in Tomcat's configuration files in tests or from within any Java SE application. 因此,您可以在测试中或从任何Java SE应用程序中访问Tomcat配置文件中配置的所有资源。 Usage is simple, eg 用法很简单,例如

TomcatJNDI tomcatJNDI = new TomcatJNDI();
tomcatJNDI.processContextXml(contextXmlFile);
tomcatJNDI.start();

DataSource ds = (DataSource) InitialContext.doLookup("java:comp/env/path/to/datasource");

Find more about it here. 在这里找到更多关于它的信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM