【发布时间】:2009-02-18 19:58:44
【问题描述】:
我正在为一个内部库(创建者早已不在)编写回归测试,并且我正在尝试验证环境。仅当 jndi 名称为“复杂”时,一些测试才因 NameNotFoundException 而失败。
这是一个独立的应用程序,不与任何网络容器一起运行。该应用程序使用首选项文件,并且不涉及 LDAP。环境是 Java v1.4,应用程序安装了所有必要的本地库。 (带有 jndi.jar、jms.jar 等的 lib 目录)。很简单吧?
由于库的复杂性以及它如何处理大量对象,我进行了一个简单的测试,然后在每个部分中增加复杂性作为单独的测试。
设置:
文件:c:\data\eclipse\workspace\APP\testfiles\jndi\jms\label\.bindings
在文件中有这个条目:QReply/FactoryName=com.ibm.mq.jms.MQQueueFactory
UnitTest 类: “简单”测试有
Hashtable ht = new Hashtable();
ht.put(Context.PROVIDER_URL,
"file:/data/eclipse/workspace/APP/testFiles/jndi/jms/label/");
ht.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.fscontext.RefFSContextFactory");
ht.put(Context.SECURITY_AUTHENTICATION, "none");
Context ctx;
try {
ctx = new InitialContext(ht);
String jndiName = "QReply";
logger.debug("testFindRemoteObject_Simple",
"Invoking InitialContext.lookup(\"" + jndiName + "\")");
Object remoteObject = ctx.lookup(jndiName);
assertTrue(remoteObject != null);
} catch (NamingException e) {
e.printStackTrace();
fail(e.getMessage());
}
这通过了。因为我在使用库时遇到了很多麻烦,所以我创建了另一个与传入的实际数据匹配的测试; Provider URL 被缩短,jndi 名称选择一个“路径”。
“实际”数据单元测试:
final Hashtable ht = new Hashtable();
ht.put(Context.PROVIDER_URL,
"file:/data/eclipse/workspace/APP/testFiles/jndi/");
ht.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.fscontext.RefFSContextFactory");
ht.put(Context.SECURITY_AUTHENTICATION, "none");
Context ctx;
try {
ctx = new InitialContext(ht);
String jndiName = "jms/label/QReply";
logger.debug("testFindRemoteObject_Actual",
"Invoking InitialContext.lookup(\"" + jndiName + "\")");
Object remoteObject = ctx.lookup(jndiName);
assertTrue(remoteObject != null);
} catch (NamingException e) {
e.printStackTrace();
fail(e.getMessage());
}
失败了
javax.naming.NameNotFoundException: jms/label/QReply
at com.sun.jndi.fscontext.RefFSContext.getObjectFromBindings(
RefFSContext.java:400)
at com.sun.jndi.fscontext.RefFSContext.lookupObject(RefFSContext.java:327)
at com.sun.jndi.fscontext.RefFSContext.lookup(RefFSContext.java:146)
at com.sun.jndi.fscontext.FSContext.lookup(FSContext.java:127)
at javax.naming.InitialContext.lookup(InitialContext.java:347)
at com.advo.tests.services.UnitTestServiceLocator.testFindRemoteObject_Actual(
UnitTestServiceLocator.java:85)
其中 UnitTestServiceLocator.java:85 是 ctx.lookup(jndiname) 的行;
为什么简单的测试会通过,而复杂的测试会失败?两者都使用指向 lib 目录的类路径,该目录填充有 jms 和 mq jar(以及其他内容)。
复杂的测试匹配库将填充的内容,但使用魔法作为传入的值。库代码还有“几行”可以从首选项文件中提取魔法值。 我错过了什么?库代码将在服务器上运行,但在我的笔记本电脑上失败(开发时)。
我什至创建了另一个 jndi 路径 - 以防第一个测试搞砸了第二个。仍然失败。
由于我没有任何愿望(或更改库代码的权限),因此调用 InitialContext(X);就是这样,因为图书馆就是这样做的。我已经看到其他示例没有通过 InitialContext 传递,我很困惑为什么这样更好。
更新: 我在 linux java1.5 上创建了一个 jndi_test 项目,并且成功运行了失败的测试。采用相同的源并将其移动到 Windows 环境 - 测试失败。由于 linux 上没有 C 盘但数据文件相同,因此类路径有一些更改。 (嗯分隔符问题?)
如果我要在 1.5 上运行它,我还发现该库存在问题,但这是一个附带问题。
【问题讨论】:
-
为了让我的生活更痛苦,库有 4 层间接,一个首选项文件指向一个服务定位器文件,该文件指向一个指向实际服务队列的 jndi 文件。