Handling Class-loaders

Some servers separate classes according to multiple class-loaders, with each thread having its own. Testing the behavior of such systems often setting the thread context class-loader and having code attempt to load classes from it. SimpleStub provides support for safely setting the thread context class-loader and priming it with test classes.

The following example tests some behavior of the Reader class. This class reads serialized data from an input stream, using the thread context class-loader to find any application-specific classes. Any class which implements the Tagged interface will have its applicationName property set to the corresponding property from its classloader (which also implements that interface).

We'll start by creating a setup class:

    abstract static class ClassLoaderControl {
        private Memento memento = Memento.NULL;

        static void install() throws NoSuchFieldException {
            memento = ThreadContextClassLoaderSupport.install(new TaggedClassLoader("test1"));
        }

        static void uninstall() {
            memento.revert();
        }
    }

We can then write some tests, assuming the existing of an appropriate class-loader class, and a method which can instantiate and serialize an instance, returning a byte array.

    @Before
    public void setUp() throws Exception {
        ClassLoaderControl.install();
    }

    @After
    public void tearDown() {
        ClassLoaderControl.uninstall();
    }

    @Test
    public void whenTaggedClassRead_setProperty() {
        ThreadContextClassLoaderSupport.createStubInThreadContextClassLoader("my.Class", BaseClass.class);
        BaseClass in = (BaseClass) Thread.current.getContextClassLoader().loadClass("my.class");
        byte[] bytes = populateAndSerialize(base);

        BaseClass out = reader.read(new ByteArrayInputStream(bytes));

        assertThat(out.getApplicationName(), is("test1"));
    }

while the Reader class is never given the classloader, and the instance is only found in the thread context classloader, the code now is able to read it, allowing us to test that behavior.