【问题标题】:Java Refactoring Strategy for Legacy Code遗留代码的 Java 重构策略
【发布时间】:2026-01-02 05:30:01
【问题描述】:

我被要求对一些遗留代码进行单元测试。

目前,代码在方法调用和使用的类型方面都与第 3 方库紧密耦合。

我的第一个想法是存根 3rd 方库(使用适当的模拟框架),以便我可以轻松地测试感兴趣的代码而不是 3rd 方库。但是,为此,我需要重构一些代码,以便将感兴趣的代码与外部库依赖隔离开来。

我最初的想法是提取一个接口并使用包装器来调用库。但是,要完全解耦库,我也需要删除库特定类型,而不仅仅是方法调用,例如

LibrarySpecificType[] myVar = wrappedLibrary.DoX();

虽然我在上面的例子中包装了我的库调用,但它仍然返回一个库特定的类型,所以它仍然有些耦合。

我该如何解决这个问题?重构代码以实现这一点的最佳策略是什么?

谢谢!

【问题讨论】:

  • 我不明白需要删除库才能测试项目。当您编写测试模拟时,您不想测试任何部分(以 mockito 为例)。
  • 我用 JMockit 发现我无法为第 3 方库创建假货。可能是因为它没有库的来源。我还觉得如果调用被包装,这样设计会更好,从而减少对库的耦合。
  • 你不需要任何源代码来伪造行为!如果是这样,请更改为另一个模拟框架。在做你应该做的事情之前,你需要进行很多重构,即编写单元测试。
  • JMockit 不使用或不需要任何源代码(除非我们谈论的是代码覆盖工具)。要从 3rd 方库中伪造类型 T,您需要为其创建 MockUp<T>。如果您尝试过但没有成功,请发布一个单独的问题,其中包含足够的信息,以便其他人可以重现该问题。
  • 感谢您的回复 Rogério - 我认为您是帮助我的人!我之前发布了这个问题没有任何运气:*.com/questions/32994290/….

标签: java unit-testing testing mocking refactoring


【解决方案1】:
  1. 我同意你的观点,为第三方库生成外观是个好主意。然后与这个外观而不是第 3 方库交谈。所以唯一引用 lib 的地方就是你的外观。

  2. LibrarySpecificType 的问题有点多。你可以再次包装它们,但这有帮助吗?不确定

  3. 至于测试。我会使用 mockito/powermockito。您可以告诉它从您的库的模拟中返回一个模拟(LibrarySpecificType)并以这种方式进行测试。显然,有一个模拟返回一个模拟是糟糕设计的标志,在这种情况下将手指指向 LibrarySpecificType

【讨论】:

  • 您好劳伦斯,感谢您的回复。您将如何包装返回值?
  • 为 3rd 方库创建一个外观可能是个好主意(前提是它简化了客户端代码,因为这就是外观的用途),但理想情况下我们应该有一个回归测试套件 这样做之前。那么有两个选择:a)没有模拟/伪造的集成测试,或b)模拟或伪造第3方库的隔离单元测试。选项 b 可以使用 PowerMock 或 JMockit(使用 mocks)或 JMockit(使用 fakes)来实现。