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

Bitte helfen Sie mir, den obigen Code zu verspotten.Junit Testing JNDI InitialContext außerhalb des Anwendungsservers

Hallo Tom Anderson

habe ich versucht, den Code unten

@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(); 
     } 
} 

Aber sein geben Fehler wie:

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

Bitte helfen Sie mir den Code zu testen Ich möchte nur Verbindung aus JNDI-Datenquelle

+0

es wirklich hängt von Ihrem App-Server ab. Irgendwelche Möglichkeiten werfen Sie einen Blick auf diese http://www.codeproject.com/Articles/25741/EJB-3-0-Remote-Session-Bean-Lookup – fGo

Antwort

18

Die o. Eine rothodoxe Sache wäre, den Code zu ändern, so dass die Context in ihn injiziert wird (durch ein Framework zur Abhängigkeitsinjektion oder manuell). Dann geben Sie einfach einen Schein in Ihrem Komponententest ein.

Wenn Sie dies nicht tun können und Ihr Code die IntialContext selbst erstellen muss, dann müssen Sie eine gefälschte JNDI-Implementierung einrichten, in die Sie Mocks injizieren können. Wenn Sie im Internet nach in-memory JNDI implementation oder mock JNDI implementation suchen, finden Sie verschiedene Optionen, oder Sie könnten selbst eine schreiben. Im Grunde benötigen Sie eine Implementierung von InitialContextFactory, die einfach einen geeigneten Schein zurückgibt, den Sie dann auswählen, indem Sie die Systemeigenschaft java.naming.factory.initial setzen.

Ich hatte einen Riss beim Schreiben der notwendigen Klassen. Hier gehen Sie:

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(); 
       } 
      } 
     }; 
    } 
} 

Verwenden Sie wie folgt vor:

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

Hallo Herr Tom Anderson .. ich versuchte den untenstehenden Code – ravichandra

+0

Hallo Herr Anderson .. Ich habe nur den Testcode bearbeitet bitte geben Sie mir einen Vorschlag – ravichandra

+0

Ihr Code ist nicht richtig. Vergleichen Sie es mit dem Originalcode von Randy Carver: https://blogs.oracle.com/randystuph/entry/injecting_jndi_datasources_for_junit. Sie tun einen 'createSubcontext', wenn Sie eine' bind' machen sollten. Die Ausnahmemeldung deutet darauf hin - Sie haben einen 'NamingContext' erstellt, in dem Sie eine' DataSource' angelegt haben sollten. –

3

Sie die Frühlings-Implementierung verwenden können, funktioniert es wie folgt aus:

import org.springframework.mock.jndi.SimpleNamingContextBuilder; 

[...] 

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

Dieses leicht mit Simple-JNDI erfolgt. Erstellen Sie eine Eigenschaftendatei „jdbc/multiDS.properties“ in Ihrem Arbeitsverzeichnis Ihrer Datenquelle mit diesen Eigenschaften zu konfigurieren:

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

dann den Kontext instanziiert mit

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); 

Danach können Sie anrufen

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

Weitere Informationen über Simple-JNDI finden Sie hier https://github.com/h-thurow/Simple-JNDI

Verwandte Themen