在java中创建模拟对象

时间:2014-03-17 14:05:30

标签: java unit-testing mocking

我正在尝试模拟一个实际上不属于测试程序的类。即 我的测试程序TestA.helloTest()调用类A的方法hello()和A.hello()调用类B的问候语()。

TestA.helloTest() - > A.hello() - > B.greetings()

我喜欢我的A类使用B的模拟对象而不是实际的实现,因为它与测试程序的目标无关。

代码中存在类似B的几个类,由于其敏感性,我们可能无法修改它们。问题是,B类既不是依赖注入的一部分也不是实现任何接口。我知道这是一个不好的做法,这个代码写的几乎是我幼儿园的时候。 :)

我认为我们只能在测试程序的上下文中注入mock。有没有办法让A类通过与JVM或Mockito协商,使用B类(或C,D,E)的模拟对象而不是实际的实现?

我很感激任何想法/投入。

2 个答案:

答案 0 :(得分:1)

您的问题分为两部分。

  1. " B类不是依赖注入的一部分"嗯,必须可以使用依赖注入来模拟它,但是如果你可以注入B类就足够了进入你的 A类 - 但是A类是你的类,所以你可以用你需要的任何方式轻松实现它!

  2. " B级没有实现任何界面":Mockito也可以模拟(非最终)类。正如 fge 在评论中写道,如果B是最终版,则使用PowerMockito。

  3. 补充:如果你不能编辑A类,有一个可能的hack。在你的测试项目中,在同一个包中用你的模拟功能创建相同的B类,并将jar(或类文件夹)放到你的类路径BEFORE包含类B的原始包.JVM将使用您的类而不是原始类:D

答案 1 :(得分:0)

一个简单的解决方案是引入调用BDelegate方法的B's(即它将所有内容委托给B),但它有一个很好的单元测试友好API。然后,您可以使用B替换代码中BDelegate的所有直接用法,并清理您的测试。

由于BDelegate中的代码非常简单,因此大多数方法都不需要进行单元测试。

另一种解决方案是更改B。是的,我知道"它不可能等等。" :-)实际上,可能便宜。我的解决方案是创建一个新项目,将JAR放入其中,其中包含B的类文件。然后在该项目中编写一个新的,更好的类B并使用JAR进行编译。

这将有效,因为对于编译,源代码始终是第一位的。因此,B将从源代码中获取,而其他所有内容都将来自JAR(因此您的新B副本将被编译)。

现在你可以在某些方面改变B(不是在所有方面,但它给你一些回旋余地)。当新B编译时,您只需将旧JAR中的旧类文件替换为新类文件,以获得更好的B

这将为您提供一个已修补的JAR文件,然后您可以在项目中使用该文件。我使用这种方法来修复Java Runtime中的错误,拒绝我的补丁或Oracle JDBC驱动程序的OSS项目,仅举几例。