2013-06-13 59 views
11
Context context = new InitialContext(); 
dataSource = (DataSource) context.lookup("java:comp/env/jdbc/multiDS"); 
connection = dataSource.getConnection(); 

上記のコードを偽装するのを手伝ってください。Junitアプリケーションサーバ外のJNDI InitialContextのテスト

こんにちはトム・アンダーソン

は、私は以下のコード

@BeforeClass 
public static void setUpClass() throws Exception { 
     // rcarver - setup the jndi context and the datasource 
     try { 
      // Create initial context 
      System.setProperty(Context.INITIAL_CONTEXT_FACTORY, 
       "org.apache.naming.java.javaURLContextFactory"); 
      System.setProperty(Context.URL_PKG_PREFIXES, 
       "org.apache.naming");    
      Context ic = new InitialContext(); 

      ic.createSubcontext("java:"); 
      ic.createSubcontext("java:comp"); 
      ic.createSubcontext("java:comp/env"); 
      ic.createSubcontext("java:comp/env/jdbc"); 
      ic.createSubcontext("java:comp/env/jdbc/multiDS"); 
      // Construct DataSource 
      OracleConnectionPoolDataSource ds = new OracleConnectionPoolDataSource(); 
      ds.setURL("jdbc:oracle:thin:@g9u0696.houston.hp.com:1525:CRNAD"); 
      ds.setUser("uname"); 
      ds.setPassword("pwd"); 
     } catch (NamingException ex) { 
      ex.printStackTrace(); 
     } 
} 

しかし、その与えてエラーをしようとしたとして:

com.hp.corona.common.exception.CacheException: org.apache.naming.NamingContext cannot be cast to javax.sql.DataSource 

私はちょうど接続からしたいコードをテストするために私を助けてくださいJNDIデータソース

+0

本当にあなたのアプリケーションサーバーによって異なります。任意の方法は、このhttp://www.codeproject.com/Articles/25741/EJB-3-0-Remote-Session-Bean-Lookup – fGo

答えて

18

ここで行うrthodoxは、Contextが(依存性注入フレームワークによって、または手動で)注入されるようにコードを変更することです。次に、単体テストの模擬試験を渡します。

これを行うことができず、自分のコードでIntialContextを作成する必要がある場合は、疑似JNDI実装を設定して、モックを注入する必要があります。ウェブでin-memory JNDI implementationまたはmock JNDI implementationを検索すると、さまざまなオプションが見つかるか、自分で書くことができます。基本的にはInitialContextFactoryの実装が必要になります。適切な模擬コードが返され、java.naming.factory.initialシステムプロパティを設定して選択します。

私は、必要なクラスを書く際に亀裂がありました。次のように

public class MockInitialContextFactory implements InitialContextFactory { 

    private static final ThreadLocal<Context> currentContext = new ThreadLocal<Context>(); 

    @Override 
    public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException { 
     return currentContext.get(); 
    } 

    public static void setCurrentContext(Context context) { 
     currentContext.set(context); 
    } 

    public static void clearCurrentContext() { 
     currentContext.remove(); 
    } 

} 

public class MockInitialContextRule implements TestRule { 

    private final Context context; 

    public MockInitialContextRule(Context context) { 
     this.context = context; 
    } 

    @Override 
    public Statement apply(final Statement base, Description description) { 
     return new Statement() { 
      @Override 
      public void evaluate() throws Throwable { 
       System.setProperty(Context.INITIAL_CONTEXT_FACTORY, MockInitialContextFactory.class.getName()); 
       MockInitialContextFactory.setCurrentContext(context); 
       try { 
        base.evaluate(); 
       } finally { 
        System.clearProperty(Context.INITIAL_CONTEXT_FACTORY); 
        MockInitialContextFactory.clearCurrentContext(); 
       } 
      } 
     }; 
    } 
} 

を使用し:ここに行く

public class FooTest { 

    private final Context context = mock(Context.class); 

    @Rule 
    public MockInitialContextRule mockInitialContextRule = new MockInitialContextRule(context); 

    @Test 
    public void testName() throws Exception { 
     // set up stubbings on the context mock 
     // invoke the code under test 
    } 
} 
+0

氏トム・アンダーソンこんにちは..私が試した次のコード – ravichandra

+0

こんにちはアンダーソン氏を見てみましょう..私はちょうどtestcodeを編集してください私に提案を与えてください – ravichandra

+0

あなたのコードは正しくありません。それをRandy Carverのオリジナルコード(https://blogs.oracle.com/randystuph/entry/injecting_jndi_datasources_for_junit)と比較してください。あなたは 'bind'をしなければならないときに' createSubcontext'をやっています。例外メッセージでは、 'DataSource'を作成したはずの' NamingContext'を作成しました。 –

3

をあなたは春の実装を使用することができ、それは次のように動作します。

import org.springframework.mock.jndi.SimpleNamingContextBuilder; 

[...] 

SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder(); 
builder.bind("jdbc/myDataSource", myDS); 
builder.activate(); 
1

これは簡単な-JNDIを使用して行われます。これらのプロパティを使用してデータソースを設定するには、作業ディレクトリの「JDBC/multiDS.properties」プロパティファイルを作成します。

type=javax.sql.DataSource 
driver=org.gjt.mm.mysql.Driver 
url=jdbc:mysql://localhost/testdb 
user=testuser 
password=testing 

は、その後、あなたが

を呼び出すことができます。その後

final Hashtable<String, String> env = new Hashtable<String, String>(); 
env.put("org.osjava.sj.root", "working_dir"); 
env.put("org.osjava.sj.jndi.shared", "true"); 
env.put("java.naming.factory.initial", "org.osjava.sj.SimpleContextFactory"); 
env.put("org.osjava.sj.delimiter", "/"); 
env.put("org.osjava.sj.space", "java:comp/env") 
Context ctx = new InitialContext(env); 

でコンテキストをインスタンス化

dataSource = (DataSource) context.lookup("java:comp/env/jdbc/multiDS"); 

Simple-JNDIの詳細はこちらhttps://github.com/h-thurow/Simple-JNDI