8

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

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

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

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

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

还假设该类的第 2 版与第 1 版不向后兼容——因此哪个版本在类路径中具有更高的优先级——它会破坏另一个版本的依赖关系。

还假设有 400 个测试依赖于很棒的模拟库——所以重写不是一个理想的选择。

还假设一些关键的业务特性是用令人惊叹的 xml 库构建的——强烈建议不要重写它。

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

4

2 回答 2

3

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

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

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

于 2013-02-28T12:48:00.913 回答
0

我认为史蒂文的回答很棒——为了完整起见,因为这个问题得到了很多选票——我想分享我们想到的所有替代方案(包括坏的)

  1. 将测试(或某些测试)划分为不同的类路径顺序(缺点 - 可能会导致您错过测试中的其他重要问题 - 这不是一个可行的选择)
  2. 回滚惊人的 xml 操作并以另一种方式实现(考虑到使用 this 的投资,以及其他操作已用尽的事实 - 这被驳回了)
  3. 使用新的模拟库重写测试(从长远来看这很好 - 在短期内这比我们当前的项目要大,因为有成百上千的项目)
  4. 构建一个使用更新版本的令人惊叹的模拟库的定制版本org.useful.XMLClass(这比我们当前的项目更大)
  5. 从源代码中提取有问题的类,并将旧版本放在覆盖源库的测试类路径中(结果证明这与其他几个类纠缠在一起 - 所以这很重要)
  6. 使用上面史蒂文的绝妙想法 - 再次证明这不是微不足道的
  7. 使用@Ignore 设置测试 - 并将它们放入队列中以便在未来的项目中重写。
于 2013-03-01T10:19:02.177 回答