2013-02-28 67 views
8

假设我有一个传统的JUnit测试套件,其中包括以下测试:解决Java类路径地狱

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

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

现在假设真棒嘲讽库依靠真棒BCEL字节码生成库,包含类org.useful.XMLClass,这个库有版本1的XMLClass。

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

同时假定类2版本与版本1向后兼容 - 所以它永远版本在classpath中具有更高的优先级 - 它打破了其他版本的依赖关系。

另外,假设有400次测试,依靠真棒嘲弄库 - 所以重写不是一个理想的选择。

同时假定一些关键的业务功能,已建成以惊人的XML libary - 和强烈优选不重写。

你如何解决这个类路径地狱的情况 - 从运行蚂蚁测试分开(假设你用Ant运行它们)有两个不同的手动排序类路径和手动确定测试子组的两倍? (我打开自定义类加载器的想法 - 但似乎差不多的水平可维护性与蚂蚁的解决方案的双定制类路径)

+0

是的,多数民众赞成在地狱。错误似乎与字节码发生器捆绑在一起的XML文件。我会建议更新你的模拟库。 – Perception 2013-02-28 12:26:10

+0

也许你可以得到“Awesome BCEL字节码生成库”的源代码,并创建一个依赖类org.useful.XMLClass的重命名版本的分支。 – gontard 2013-02-28 12:28:52

+1

我同意没有简单的答案。也许你可以尝试使用自定义类加载器......但这看起来似乎比它的价值更努力。我会用XML库或模拟操作的新库重写测试。 – RudolphEst 2013-02-28 12:43:14

回答

3

我相信一个相当透明的解决方案可能是使用Java代理和自定义类装载机。这个想法如下:

  1. 使用Instrumentation Framework(java代理程序)加载它们时拦截类。当您检测到Awesome Mocking Library中的类时,请将所有对org.useful.XMLClass的引用替换为例如intercepted.org.useful.XMLClass
  2. 创建一个自定义的类装载器,在您检查所请求的类是intercepted.org.useful.XMLClass。如果是,请加载由Mocking Library使用的版本XMLClass。所有其他请求都可以默认处理。

运行测试时,使用自定义类加载器并附加java代理,并且所有内容都应该正常运行,就好像没有依赖冲突一样。

+0

这真的很棒。有没有一种方法来加载现有类路径的副本版本并在运行时对其进行修改 - 即同样的效果,但不使用代理? – hawkeye 2013-02-28 21:46:34

+0

我不完全确定你的意思,但是如果不使用代理来区分不同版本的XMLClass,运行时如何能够从哪个点决定使用哪个版本? – Steven 2013-02-28 23:17:07

+0

优秀的解决方案! – gontard 2013-03-19 12:06:16

0

我认为史蒂芬的答案是伟大的 - 为了完整起见,因为这个问题有这么多的选票 - 我想和大家分享我们所认为的替代品(包括坏的)

  1. 分区测试(或一些测试)进入不同的类路径顺序 (劣势 - 可能导致您错过其他测试的重要问题 - 不是一个可行的选项)
  2. 回滚令人惊叹的xml操作并实现另一种方式(由于投资在这方面的使用,以及其他行动已经耗尽的事实 - 这是被驳回的)
  3. 重写使用新的嘲弄库测试(这是在长期良好 - 在短期内这一工程以比我们目前的项目更大,因为有成百上千)
  4. 打造的定制版使用更新版本的org.useful.XMLClass(结果比我们目前的项目更大)的惊人嘲笑库
  5. 从源文件中提取出有问题的类,并将旧版本放在测试类路径上覆盖源库这与其他几个课程纠缠在一起 - 所以这不是微不足道的)
  6. 在上面使用史蒂文的奇妙创意 - 再次证明这不是微不足道的
  7. 使用@Ignore设置测试 - 并将它们放入队列中,以便在未来的项目中进行重写。