在遗留的junit测试套件中解决java classpath地狱

时间:2013-02-28 12:16:37

标签: java junit dependencies classpath

假设我有一个包含以下测试的遗留JUnit测试套件:

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

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

现在假设Awesome Mocking库依赖于包含类org.useful.XMLClass的Awesome BCEL字节码生成库,并且该库具有XMLClass的版本1。

现在假设Amazing Xml操作依赖于包含类org.useful.XMLClass的Amazing Xml库,并且该库具有XML Class的第2版。

还假设该类的版本2不向后兼容版本1 - 因此哪个版本在类路径中具有更高的优先级 - 它打破了另一个版本的依赖性。

还假设有400个测试依赖于令人敬畏的模拟库 - 所以重写不是一个理想的选择。

还假设一些关键业务功能已经使用了惊人的xml库构建 - 并且强烈建议不要重写它。

你如何解决这个类路径地狱的情况 - 除了运行ant测试(假设你用Ant运行它们)两次,两个不同的手动排序的类路径和手动确定的测试子集? (我对自定义类加载器的想法持开放态度 - 但这似乎与使用ant解决方案的双自定义类路径具有相同的可维护性水平)

2 个答案:

答案 0 :(得分:3)

我相信使用java代理和自定义类加载器可以实现一个非常透明的解决方案。这个想法如下:

  1. 使用Instrumentation Framework(java代理)在加载类时拦截它们。当您检测到Awesome Mocking Library中的类时,请将对org.useful.XMLClass的所有引用替换为intercepted.org.useful.XMLClass
  2. 创建一个自定义类加载器,在其中检查所请求的类是否为intercepted.org.useful.XMLClass。如果是,请加载Mocking Library使用的XMLClass版本。默认情况下,可以处理所有其他请求。
  3. 使用自定义类加载器并在运行测试时附加java代理,并且所有内容都应该正确运行,就像没有依赖冲突一样。

答案 1 :(得分:0)

我认为史蒂文的答案很棒 - 为了完整起见,因为这个问题获得了如此多的选票 - 我想分享我们想到的所有替代品(包括不好的选择)

  1. 将测试(或某些测试)分成不同的类路径顺序 (缺点 - 可能会导致您错过测试中的其他重要问题 - 不是一个可行的选择)
  2. 回滚惊人的xml操作并实施另一种方式(考虑到对此的使用投资,以及其他操作已经用尽的事实 - 这被解雇了)
  3. 使用新的模拟库重写测试(这在长期内是好的 - 在短期内,这比我们当前的项目更大,因为有数百个数百个)
  4. 构建使用较新版org.useful.XMLClass的惊人模拟库的自定义版本(结果比我们当前的项目更大)
  5. 从源代码中提取出有问题的类,并将旧版本放在测试类路径上,覆盖源库(事实证明这与其他几个类纠缠在一起 - 所以这非常重要)
  6. 使用史蒂文上面的奇妙想法 - 再次证明这是非平凡的
  7. 使用@Ignore设置测试 - 并将它们放入队列以重写未来的项目。