如何模拟 JNDI 对象以便单元测试呢?首先需要加入 tomcat-juli.jar,这个包位于 `tomcat/bin` 目录下,需要手动复制到 Classpath 中;然后生成初始化上下文对象 InitialContext,下面就封装了一个方法 JdbcConnection.initIc();最后绑定实际数据源对象DataSource,源码如下。
private static InitialContext initIc() {
System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.naming.java.javaURLContextFactory");
System.setProperty(Context.URL_PKG_PREFIXES, "org.apache.naming");
try {
InitialContext ic = new InitialContext();
ic.createSubcontext("java:");
ic.createSubcontext("java:/comp");
ic.createSubcontext("java:/comp/env");
ic.createSubcontext("java:/comp/env/jdbc");
return ic;
} catch (NamingException e) {
LOGGER.warning(e);
return null;
}
}
// 绑定数据源
/**
* 根据 JDBC Url 创建 MySQL 数据库 JDNI 数据源
*
* @param url 像 "jdbc:mysql://localhost:3306/databaseName"
* @param user 用户名
* @param password 密码
*/
public static void initMySqlDBConnection(String url, String user, String password) {
try {
initIc().bind("java:/comp/env/jdbc/mysql", getMySqlDataSource(url, user, password));
} catch (NamingException e) {
LOGGER.warning(e);
}
}
/**
* 根据 JDBC Url 创建 SQLite 数据库 JDNI 数据源。
*
* @param url 以 jdbc:sqlite: 开头
*/
public static void initSqliteDBConnection(String url) {
DataSource ds = getSqliteDataSource(url);
try {
initIc().bind("java:/comp/env/jdbc/sqlite", ds);
} catch (NamingException e) {
LOGGER.warning(e);
}
}
接着需要把 DataSource 对象与 InitialContext 绑定关联起来,执行这一步的具体方法有 initMySqlDBConnection() 和 initSqliteDBConnection(),分别对应 MySQL 和 SQLite 数据库。最后在单元测试中指定 JDNI 路径即可,如下例:
DataSourceJdbcConnection.getDataSource("jdbc/mysql_test")。
本文的函数位于 AJAXJS 框架的 JdbcConnection 类,完整代码在 https://gitee.com/sp42_admin/ajaxjs/blob/master/aj-base/src/main/java/com/ajaxjs/sql/JdbcConnection.java。