복붙노트

[SPRING] Spring에서 조롱 된 JNDI 데이터 소스를 테스트하는 방법은 무엇입니까?

SPRING

Spring에서 조롱 된 JNDI 데이터 소스를 테스트하는 방법은 무엇입니까?

나는 Spring에 상당히 새로운 것이고 조롱 된 데이터 소스를 사용하는 JUnit 테스트를 만드는 방법과 JNDI 컨텍스트를 사용하는 방법을 궁금해하십니까? 현재 내 응용 프로그램은 Tomcat의 JNDI 컨텍스트를 사용하여 연결을 검색하고 해당 연결을 통해 데이터베이스에서 데이터를 검색합니다. 그래서 나는 JNDI 호출과 데이터 검색을 조롱 할 필요가 있다고 생각한다. 이 문제를 해결할 수있는 가장 좋은 방법에 대한 좋은 조언이 될 것입니다. 고마워요!

해결법

  1. ==============================

    1.보통 datasource-context.xml과 같은 별도의 파일에 내 JNDI 종속성을 정의합니다.

    보통 datasource-context.xml과 같은 별도의 파일에 내 JNDI 종속성을 정의합니다.

    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:jee="http://www.springframework.org/schema/jee"
        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
            http://www.springframework.org/schema/jee
            http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
    
        <jee:jndi-lookup id="dataSource" 
            jndi-name="java:comp/env/dataSource" 
            expected-type="javax.sql.DataSource" />
    
    </beans>
    

    그래서 테스트 리소스에서 나는 다른 파일을 생성하고 테스트 데이터 소스를 정의 할 수 있습니다. datasource-testcontext.xml과 같이 저에게 적합합니다 :

    <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="org.hsqldb.jdbcDriver"
            p:url="jdbc:hsqldb:hsql://localhost:9001"
            p:username="sa"
            p:password="" /> 
    
    </beans>
    

    그리고 나서 테스트 클래스에서 JNDI에 의존하는 프로덕션 대신 데이터 소스의 테스트 구성을 사용합니다.

    @ContextConfiguration({
        "classpath*:META-INF/spring/datasource-testcontext.xml",
        "classpath*:META-INF/spring/session-factory-context.xml"
    })
    public class MyTest {
    
    }
    

    데이터 소스가 별도의 파일에 정의되지 않은 경우 JNDI 호출에서 반환 된 객체를 쉽게 스텁링 할 수 있습니다.

  2. ==============================

    2.SimpleNamingContextBuilder를 사용하여 jndi 데이터 소스를 테스트에 사용할 수 있습니다.

    SimpleNamingContextBuilder를 사용하여 jndi 데이터 소스를 테스트에 사용할 수 있습니다.

        SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
        builder.bind("java:comp/env/jdbc/mydatasource", dataSource);
        builder.activate();
    

    https://fisheye.springsource.org/browse/spring-framework/spring-test/src/main/java/org/springframework/mock/jndi/SimpleNamingContextBuilder.java?hb=true

    이것은 데이터 소스를 정확하게 조롱하지 않지만 테스트를 위해 jndi를 통해 데이터 소스를 사용할 수 있도록합니다.

  3. ==============================

    3.Spring의 AbstractDataSource를 확장하여 자신 만의 DataSource를 만들 수있다.

    Spring의 AbstractDataSource를 확장하여 자신 만의 DataSource를 만들 수있다.

    import java.sql.Connection;
    import java.sql.SQLException;
    
    import org.springframework.jdbc.datasource.AbstractDataSource;
    
    /**
     * Mock implementation of DataSource suitable for use in testing.
     * 
     *
     */
    public class MockDataSource extends AbstractDataSource {
        private Connection connection;
    
        /**
         * Sets the connection returned by javax.sql.DataSource#getConnection()
         * and javax.sql.DataSource#getConnection(java.lang.String, java.lang.String)
         * 
         * @param connection
         */
        public void setConnection(Connection connection) {
            this.connection = connection;
        }
    
        /*
         * (non-Javadoc)
         * @see javax.sql.DataSource#getConnection()
         */
        public Connection getConnection()
                throws SQLException {
            return connection;
        }
    
        /*
         * (non-Javadoc)
         * @see javax.sql.DataSource#getConnection(java.lang.String, java.lang.String)
         */
        public Connection getConnection(String username, String password)
                throws SQLException {
            return connection;
        }
    }
    

    연결의 JNDI 조회를 나머지 코드와 구분합니다. 데이터 액세스 개체 (DAO)에 데이터 소스를 주입하고 DAO 테스트를 위해 MockDataSource를 사용하십시오.

  4. ==============================

    4.언제든지 beans.xml을 참조하는 bean.test.xml 구성을 만든 다음 데이터 소스 구성을 재정의 할 수 있습니다.

    언제든지 beans.xml을 참조하는 bean.test.xml 구성을 만든 다음 데이터 소스 구성을 재정의 할 수 있습니다.

    src / main / resources / beans.xml

    <!-- Database configuration -->
    <import resource="beans.datasource.jndi.xml" />
    

    src / test / resources / beans.test.xml

    <import resource="beans.xml" />
    <import resource="beans.datasource.test.xml" />
    

    JUnit 테스트 클래스 :

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = { "classpath:/beans.test.xml" })
    public class ASRTests
    {
    ...
    }
    

    jndi bean에서 참조를 선언하십시오.

    <jee:jndi-lookup expected-type="javax.sql.DataSource" id="mysqlDataSource" jndi-name="jdbc/mysql"/>
    

    테스트 빈에서 데이터 소스를 선언하십시오.

    <bean id="mysqlDataSource" ...>
    ...
    </bean>
    

    테스트 데이터 소스 빈을 테스트 폴더로 이동하는 것을 명심하십시오.

  5. ==============================

    5.Spring의 org.springframework.jndi.JndiObjectFactoryBean은 JNDI 룩업에 가장 적합하다. 그것의 문서에 따라, 그것은 스프링 기반 테스트 케이스를위한 디폴트 값을 주입하는 것을 허용한다.

    Spring의 org.springframework.jndi.JndiObjectFactoryBean은 JNDI 룩업에 가장 적합하다. 그것의 문서에 따라, 그것은 스프링 기반 테스트 케이스를위한 디폴트 값을 주입하는 것을 허용한다.

    아래 spring 설정 (spring-test-db-config.xml로 이름 지어 짐)을 참조하십시오.

    <bean id="dataSource" class="oracle.jdbc.pool.OracleDataSource">
        <property name="URL" value="jdbc:oracle:thin:@localhost:1521:XE"/>
        <property name="user" value="UNITTEST"/>
        <property name="password" value="UNITTEST"/>
    </bean>
    
    <bean id="dataSourceFromJndi" class="org.springframework.jndi.JndiObjectFactoryBean">
        <!-- Any junk value will suffice as that is always gonna throw NamingException -->
        <property name="jndiName" value="jdbc/Ds"/>
        <property name="defaultObject" ref="dataSource"/>
    </bean>
    

    다른 설정 파일에 정의 된 Bean 추가는 JNDI bean의 dataSource를 참조한다.

    <!-- START OF SERVICES -->
    <bean class="com.sample.Service" >
        <property name="dataSource" ref="dataSourceFromJndi" />
    </bean>
    

    이 접근법의 장점은 프로덕션 용과 유닛 테스트 용의 두 가지 DB 구성 파일을 유지할 수 있다는 것입니다. 올바른 것을 가져 오십시오. 테스트 구성에는 기본 객체가 포함됩니다.

  6. ==============================

    6.자바 구성 .....

    자바 구성 .....

    Junit 테스트 케이스

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = {DatabaseConfigStub.class}, loader= AnnotationConfigContextLoader.class)
    public class DatabaseConfigTest  {
    
    @Autowired
    private DataSource datasource;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    
    @Before
    public void setUp() throws Exception {
    
    }
    
    @After
    public void tearDown() throws Exception {
    }
    
    @Test
    public void testDataSource() {
        assertNotNull(datasource);
        assertNotNull(jdbcTemplate);
    }
    
    }
    

    DatabaseConfig 스텁

    public class DatabaseConfigStub {
    
    private static final Logger log = Logger.getLogger(DatabaseConfigStub.class);
    
            private static final String DS_NAME = "jdbc/DS_NAME";
    
    @Bean
    DataSource dataSource() {
        JndiObjectFactoryBean jndiObjectBean = EasyMock.createMock(JndiObjectFactoryBean.class);
        jndiObjectBean.setJndiName(DS_NAME);
        jndiObjectBean.setResourceRef(true);
        jndiObjectBean.setProxyInterfaces(DataSource.class);
    
        EasyMock.expect( (DataSource)jndiObjectBean.getObject()).andReturn(new DataSource() {
    
                public <T> T unwrap(Class<T> iface) throws SQLException {
                    // TODO Auto-generated method stub
                    return null;
                }
    
                public boolean isWrapperFor(Class<?> iface) throws SQLException {
                    // TODO Auto-generated method stub
                    return false;
                }
    
                public void setLoginTimeout(int seconds) throws SQLException {
                    // TODO Auto-generated method stub
    
                }
    
                public void setLogWriter(PrintWriter out) throws SQLException {
                    // TODO Auto-generated method stub
    
                }
    
                public int getLoginTimeout() throws SQLException {
                    // TODO Auto-generated method stub
                    return 0;
                }
    
                public PrintWriter getLogWriter() throws SQLException {
                    // TODO Auto-generated method stub
                    return null;
                }
    
                public Connection getConnection(String username, String password)
                        throws SQLException {
                    // TODO Auto-generated method stub
                    return null;
                }
    
                public Connection getConnection() throws SQLException {
                    // TODO Auto-generated method stub
                    return null;
                }
            }
        );
        EasyMock.replay(jndiObjectBean);
    
        return (DataSource) jndiObjectBean.getObject();
    }
    
    @Bean
    JdbcTemplate jdbcTemplate(){
        return new JdbcTemplate( dataSource());
    }
    

    }

  7. ==============================

    7.Simple-JNDI를 사용할 수도 있습니다. 이것은 J2EE 컨테이너 외부의 JNDI 컨텍스트에 대한 작업을위한 메모리 내 JNDI 구현입니다. 생산 및 테스트에서 동일한 bean 정의 파일을 사용할 수 있습니다. 생산중인 bean 정의라고 가정합니다.

    Simple-JNDI를 사용할 수도 있습니다. 이것은 J2EE 컨테이너 외부의 JNDI 컨텍스트에 대한 작업을위한 메모리 내 JNDI 구현입니다. 생산 및 테스트에서 동일한 bean 정의 파일을 사용할 수 있습니다. 생산중인 bean 정의라고 가정합니다.

    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="java:comp/env/jdbc/DataSource"/>
    </bean>
    <bean id="dao" class="my.Dao">
        <property name="dataSource" ref="dataSource" />
    </bean>
    

    이런 속성 파일을 만듭니다.

    type=javax.sql.DataSource
    driverClassName=org.gjt.mm.mysql.Driver
    url=jdbc:mysql://localhost/testdb
    username=user_name
    password=password
    

    Simple-JNDI와 jndi.properties 파일을 클래스 경로에 약간의 구성으로 넣으십시오. 그런 다음 평상시처럼 데이터 소스에 액세스하십시오.

    Simple-JNDI에 대한 자세한 내용은 여기를 참조하십시오.

  8. from https://stackoverflow.com/questions/5940895/how-to-test-a-mocked-jndi-datasource-with-spring by cc-by-sa and MIT license