web-dev-qa-db-fra.com

Junit Testing JNDI InitialContext en dehors du serveur d'applications

Context context = new InitialContext();
dataSource = (DataSource) context.lookup("Java:comp/env/jdbc/multiDS");
connection = dataSource.getConnection();

S'il vous plaît, aidez-moi à me moquer du code ci-dessus.

Salut Tom Anderson

J'ai essayé le code ci-dessous

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

Mais son erreur donnant comme:

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

Aidez-moi à tester le code que je veux juste connexion à partir de la source de données JNDI

22
ravichandra

La chose orthodoxe à faire ici serait de changer votre code pour que le Context y soit injecté (par un framework d'injection de dépendances, ou manuellement). Ensuite, vous passez simplement une maquette dans votre test unitaire.

Si vous ne pouvez pas le faire et que votre code doit créer le IntialContext lui-même, vous devrez configurer une fausse implémentation JNDI dans laquelle vous pouvez injecter des simulations. Si vous recherchez sur le Web implémentation JNDI en mémoire ou implémentation JNDI simulée , vous trouverez différentes options, ou vous pourriez en écrire une vous-même. Fondamentalement, vous aurez besoin d'une implémentation de InitialContextFactory qui renvoie simplement une maquette appropriée, que vous sélectionnez ensuite en définissant le Java.naming.factory.initial propriété système.

J'ai eu du mal à écrire les cours nécessaires. Voici:

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

Utilisez comme suit:

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
    }
}
24
Tom Anderson

Vous pouvez utiliser l'implémentation Spring, cela fonctionne comme ceci:

import org.springframework.mock.jndi.SimpleNamingContextBuilder;

[...]

SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
builder.bind("jdbc/myDataSource", myDS);
builder.activate();
7
Michael Böckling

Cela se fait facilement avec Simple-JNDI. Créez un fichier de propriétés "jdbc/multiDS.properties" dans votre répertoire de travail pour configurer votre source de données avec ces propriétés:

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

Instanciez ensuite le contexte avec

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

Après cela, vous pouvez appeler

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

Trouvez plus d'informations sur Simple-JNDI ici https://github.com/h-thurow/Simple-JNDI

2
Holger Thurow