Mock JNDI Provider
Unit testing JNDI enabled code is difficult; to be done properly it should be done with a mock JNDI provider that can provide basic responses to JNDI / LDAP calls. The JXplorer project includes a mock JNDI provider for this purpose (cross-donated from the pegacat.com GroupMind project.)
Using this provider allows for unit testing of basic tree manipulation, directory searches and entry reading, allowing for LDAP aware code to be unit tested in a similar way to how JDBC database code might be unit tested.
It provides support for the basic JNDI operations (as used by a GUI client such as JXplorer):
- read entries
- write entries
- modify entries
- search entries
- Base Entry search
- One level search
- Sub tree search
- Search Filters (see note).
There is some support for complex search filters such as:
(&(!(|(cn=Fred)(cn=Nigel)))(objectClass=Topic)) or (&(objectClass=Person)(|(sn=Jensen)(cn=Babs J*))).. however this has only been tested to the extent required for current test cases, and should not be relied on as a general purpose search filter.
It does *not* support:
- binding java objects - the logon methods are not implemented. Users will need to do their own serialisation if they want this functionality.
- no referrals
- no ldap v3 extensions.
- no composite names spanning multiple namespaces - all names are LDAP names only. (Composite names have proved a problematic part of JNDI - personally I've never found them very useful - CB)
- thread safety; it is intended to be run single threaded during testing, and was not built with thread safety in mind, so you're on your own there...
If you need the above features, you should probably plan to use system tests and a real directory.
Code
The Mock JNDI Provider is in the source code package com.pegacat.testprovider, and also packaged as a standalone zip file as part of the JX 3.3 release. Look in the com.pegacat.testprovider.TestProviderContextTest class for usage examples.
Download
The following zip file contains both source and a jar file: jxplorer-3.3-testprovider.zip
Usage
The JNDI Mock maintains an internal hashtable of entries. To use the provider it should normally be 'primed' with a base set of entries - this can be done in the setup() method of a junit test case. For example:
String nameString[] = {"", // 0 "c=au", // 1 "o=pegacat,c=au", // 2 "ou=research,o=pegacat,c=au", // 3 "cn=Fred,ou=research,o=pegacat,c=au", // 4 "cn=Eric,ou=research,o=pegacat,c=au", // 5 "cn=john,ou=research,o=apache,c=us"}; // 6 public void testSetUp() throws Exception { //initialise with empty properties hashtable ctx = (TestProviderContext) new TestProviderContextFactory().getInitialContext(new Hashtable()); //create initial entry tree using name list above and dummy attribute values for (int i = 0; i < nameString.length; i++) { LdapName name = new LdapName(nameString[i]); TreeEntry entry = new TreeEntry(name); if (i>3) { entry.put("objectClass", "person"); entry.put("cn", name.getRdn(name.size()-1).getValue()); entry.put("sn", "Smith"); entry.put("userPassword", JndiTools.shaEncode("fnord")); } ctx.createSubcontext(name, entry); } // print out created tree ctx.getEntries().dump(); }
Obviously more complex entries with more attributes are possible. Bear in mind that the test provider does very limited schema checking, so it is still possible to write code in a unit test that will fail against a production directory.