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):

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:

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.