I am trying to set up some jUnit testing. Our database is connected by the server using JNDI. We have an xml describing the setup in root.xml. How do I set up jUnit to hook up to the database? I'd prefer to have it just read the the stuff off of root.xml, but I'm open to setting it up anyway that works.
问题:
回答1:
I've found this Blog: https://blogs.oracle.com/randystuph/entry/injecting_jndi_datasources_for_junit
About H2 Datasource: http://www.h2database.com/javadoc/org/h2/jdbcx/JdbcConnectionPool.html
So for my Code:
package com.example.test;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import org.h2.jdbcx.JdbcConnectionPool;
import junit.framework.TestCase;
public class JunitDataSource extends TestCase {
public void setUp() 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");
InitialContext ic = new InitialContext();
ic.createSubcontext("java:");
ic.createSubcontext("java:/comp");
ic.createSubcontext("java:/comp/env");
ic.createSubcontext("java:/comp/env/jdbc");
JdbcConnectionPool ds = JdbcConnectionPool.create(
"jdbc:h2:file:src/main/resources/test.db;FILE_LOCK=NO;MVCC=TRUE;DB_CLOSE_ON_EXIT=TRUE", "sa", "sasasa");
// Construct DataSource
// OracleConnectionPoolDataSource ds = new
// OracleConnectionPoolDataSource();
// ds.setURL("jdbc:oracle:thin:@host:port:db");
// ds.setUser("MY_USER_NAME");
// ds.setPassword("MY_USER_PASSWORD");
ic.bind("java:/mydatasourcename", ds);
} catch (NamingException ex) {
Logger.getLogger(JunitDataSource.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void testSimple() throws Exception {
// Obtain our environment naming context
Context initCtx = new InitialContext();
// Look up our datasource
DataSource ds = (DataSource) initCtx.lookup("java:/mydatasourcename");
Connection conn = ds.getConnection();
Statement stmt = conn.createStatement();
ResultSet rset = stmt.executeQuery("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES");
while (rset.next()) {
System.out.println("<<<\t"+rset.getString("TABLE_NAME"));
}
}
}
Note: I had to add Tomcat Library and the jars inside the Tomcat's bin directory to get it working
回答2:
I found that the best way to do it is to use something called Simple-Jndi.
I added this to the maven file:
<dependency>
<groupId>simple-jndi</groupId>
<artifactId>simple-jndi</artifactId>
<version>0.11.4.1</version>
<scope>test</scope>
</dependency>
You can download the the package here, the download contains an instruction manual. http://code.google.com/p/osjava/downloads/detail?name=simple-jndi-0.11.4.1.zip&can=2&q=
After adding to to your project you just have to add a couple of properties files, per the instructions.
However, after you add the dependency, I believe you can add your jndi resources programmatically instead of using properties files. You do something like this: (new InitialContext()).rebind("datasource",myDatasource);
回答3:
I have used Simple-JNDI for this purpose for years now. It gives you an in-memory implementation of a JNDI Service and allows you to populate the JNDI environment with objects defined in property files. There is also support for loading datasources or connection pools configured in a file.
To get a connection pool you have to create a file like this:
type=javax.sql.DataSource
driver=com.sybase.jdbc3.jdbc.SybDriver
pool=myDataSource
url=jdbc:sybase:Tds:servername:5000
user=user
password=password
In your application you can access the pool via
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("path/to/your/connectionPool");
You can find more about it at https://github.com/h-thurow/Simple-JNDI.
TomcatJNDI helps with that situation too. It can process Tomcat’s configuration files and creates the same JNDI environment as Tomcat does, but without starting a server. So you can run classes with dependencies on Tomcat’s JNDI environment in e. g. JUnit tests.
TomcatJNDI tomcatJNDI = new TomcatJNDI();
tomcatJNDI.processContextXml(new File(“tomcat-root-dir/conf/context.xml”);
tomcatJNDI.start();
Then your classes can lookup the DataSource as when they would run in Tomcat.
More about TomcatJNDI can be found here: https://github.com/h-thurow/TomcatJNDI
回答4:
Would you like to create datasource programmatically on Application Server? Referene :
- Create Datasource JBoss 7 from program
- Create Datasource Weblogic from program
If you already created on Sever,
public class YourTestCase {
private java.sql.Connection conn;
@BeforeClass
public static void init() {
/* Weblogic */
try {
Context ctx = null;
Hashtable ht = new Hashtable();
ht.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
ht.put(Context.PROVIDER_URL, "t3://<your-host>:<your:post>");
ctx = new InitialContext(ht);
javax.sql.DataSource ds = (javax.sql.DataSource) ctx.lookup ("<your-datasource-jndi-name>");
conn = ds.getConnection();
} catch(Exception e) {
}
/* JBoss 5*/
Context.INITIAL_CONTEXT_FACTORY ---> org.jnp.interfaces.NamingContextFactory
Context.PROVIDER_URL ---->http://localhost:1099
}
@AfterClass
public static void finished() {
}
@Test
public void testMethod() {
try {
Statement stmt = conn.createStatement();
stmt.execute("select * from someTable");
ResultSet rs = stmt.getResultSet();
// do operation
stmt.close();
conn.close();
} catch (Exception e) {
// a failure occurred
} finally {
try {ctx.close();
} catch (Exception e) {
}
}
}
}
}
回答5:
You can add Tomcat lib via maven dependency using below, to get it working.
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>catalina</artifactId>
<version>6.0.18</version>
<scope>test</scope>
</dependency>
回答6:
I think you should try to mock out the database. Use appropriate framework, for example Mockito, it creates mocks and have DI abilities.