Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Solving java classpath hell in legacy junit test suite

Suppose I have a legacy JUnit test suite that includes the following tests:

public class AwesomeTest {
     public void testBusinessLogic() {
     ...
     [awesome mocking library]
     ...
     }
}

public class AmazingTest {
    public void testBusinessProcess() {
    ...
    [amazing xml operation]
    ...
    }
}

Now assume that Awesome Mocking library relies on Awesome BCEL bytecode generation library which contains the class org.useful.XMLClass and this library has version 1 of XMLClass.

Now assume that Amazing Xml operation relies on Amazing Xml Library that contains the class org.useful.XMLClass and this library has version 2 of XML Class.

Also assume that version 2 of the class is not backwards compatible with version 1 - so which ever version has higher priority in the classpath - it breaks the dependencies of the other version.

Also assume that there are 400 tests that rely on awesome mocking library - so rewriting is not a desirable option.

Also assume that some critical business features have been built with amazing xml libary - and it is strongly preferred not to rewrite that.

How do you solve this classpath hell situation - apart from running the ant tests (assuming you're running them with Ant) twice with two differently manually ordered classpaths and manually determined test sub-sets? (I'm open to an idea with custom classloaders - but that seems about the same level of maintainability as the dual custom classpath with ant solution)

like image 329
hawkeye Avatar asked Feb 28 '13 12:02

hawkeye


1 Answers

I do believe a quite transparent solution is possible using a java agent and custom class loader. The idea is the following:

  1. Use the Instrumentation Framework (java agent) to intercept the classes when they are loaded. When you detect a class that is in the Awesome Mocking Library, replace all references to org.useful.XMLClass to, for example, intercepted.org.useful.XMLClass.
  2. Create a custom class loader, in which you check if the requested class is intercepted.org.useful.XMLClass. If it is, load the version of XMLClass that is used by the Mocking Library. All other requests can be handled by default.

Use the custom class loader and attach the java agent when running the tests, and everything should run correctly, as if there is no dependency conflict.

like image 172
Steven Avatar answered Nov 14 '22 11:11

Steven