我正在为一个内部库编写回归测试(其创建者已经离开很久了),并尝试验证环境。其中几个测试在JNDI名称为“complex”时失败,并显示NameNotFoundException。
该应用程序是独立的,没有运行在任何Web容器中。该应用程序使用偏好文件,没有涉及LDAP。环境为Java v1.4,并且安装了所有必要的本地库(包括jndi.jar、jms.jar等)。
由于库的复杂性以及它如何与许多对象交互,我先进行简单测试,然后逐步增加复杂度,将每个部分作为单独的测试添加进去。
设置: 文件:c:\data\eclipse\workspace\APP\testfiles\jndi\jms\label\.bindings
文件中有以下条目:QReply/FactoryName=com.ibm.mq.jms.MQQueueFactory
单元测试类: “simple”测试包含以下内容:
该应用程序是独立的,没有运行在任何Web容器中。该应用程序使用偏好文件,没有涉及LDAP。环境为Java v1.4,并且安装了所有必要的本地库(包括jndi.jar、jms.jar等)。
由于库的复杂性以及它如何与许多对象交互,我先进行简单测试,然后逐步增加复杂度,将每个部分作为单独的测试添加进去。
设置: 文件:c:\data\eclipse\workspace\APP\testfiles\jndi\jms\label\.bindings
文件中有以下条目:QReply/FactoryName=com.ibm.mq.jms.MQQueueFactory
单元测试类: “simple”测试包含以下内容:
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());
}
这个测试通过了。因为我在使用库的过程中遇到了很多问题,所以我创建了另一个测试,匹配传入的实际数据;提供者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上运行它,那个库会出问题,但这是一个次要问题。