2013-06-13 32 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

o這裏要做的東西是改變你的代碼,以便Context被注入(通過依賴注入框架或手動注入)。然後,你只需在你的單元測試中進行模擬。

如果你不能這樣做,而你的代碼必須自己創建IntialContext,那麼你將需要建立一個假的JNDI實現,你可以注入mock。如果您在網上搜索in-memory JNDI implementationmock 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

您好安德森先生..我剛剛編輯的測試代碼,請給我建議 – ravichandra

+0

你的代碼是不正確的。將其與Randy Carver的原始代碼進行比較:https://blogs.oracle.com/randystuph/entry/injecting_jndi_datasources_for_junit。當你應該做一個'bind'的時候你正在做一個'createSubcontext'。這個異常信息暗示了這一點 - 你已經創建了一個'NamingContext',你應該創建一個'DataSource'。 –

3

您可以使用Spring實現,它的工作原理是這樣的:

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