如何模拟对象构造?
有没有一种方法可以在Java中使用JMock来模拟对象构造?
例如,如果我有这样的方法:
public Object createObject(String objectType) { if(objectType.equals("Integer") { return new Integer(); } else if (objectType.equals("String") { return new String(); } }
...是否有一种方法可以在测试方法中模拟对象构造的期望?
我希望能够期望某些构造函数被调用,而不必花费额外的代码来检查类型(因为它并不总是像我的示例那样复杂和简单)。
因此,而不是:
assertTrue(a.createObject() instanceof Integer);
我可以期望某些构造函数被调用。只是为了使其更加干净,并以更具可读性的方式表示实际正在测试的内容。
请原谅简单的示例,我正在处理的实际问题要复杂一些,但是有了期望会简化它。
有关更多背景信息:
我有一个简单的工厂方法,它创建包装对象。被包装的对象可能需要很难在测试类(它是预先存在的代码)中获取的参数,因此很难构造它们。
也许更接近我真正要寻找的是:是否有一种方法可以一次模拟整个类(使用CGLib),而无需指定要进行存根的每个方法?
因此,模拟程序被包装在构造函数中,因此显然可以在其上调用方法,JMock是否能够动态模拟出每个方法?
我的猜测不是,因为那将非常复杂。但是知道我在吠错树也是很有价值的:-)
解决方案
我希望没有。
嘲笑应该模拟接口,没有构造函数...只是方法。
我们在这里进行测试的方法似乎有些不对劲。为什么需要测试是否调用了显式构造函数的任何原因?
断言返回对象的类型对于测试工厂实现似乎是可以的。将createObject视为黑匣子。.检查返回的内容,但不进行微观管理。没有人喜欢:)
更新更新:太好了!拼命的措施,拼命的时候是吗?如果JMock允许它,我会感到惊讶。正如我说的那样,它可以在接口上工作。
所以
- 或者尽力使那些讨厌的输入对象在测试工具下"可实例化"。自下而上。
- 如果这不可行,请使用断点进行手动测试(我知道它很糟糕)。然后在源文件的可见区域中添加"自行承担风险触摸"注释,然后继续。再战一天。
我唯一能想到的就是在工厂对象上创建create方法,而不是模拟它。
但是就模拟构造函数调用而言,没有。模拟对象以对象的存在为前提,而构造函数以对象不存在为前提。至少在Java中,分配和初始化同时发生。
我们熟悉依赖注入吗?
如果没有,那么我们将自然而然地从对该概念的学习中受益。我猜想马丁·福勒(Martin Fowler)的过时的控制容器反转和"依赖注入"模式将是一个很好的介绍。
使用依赖注入(DI),我们将拥有一个DI容器对象,该对象能够为我们创建各种类。然后,对象将利用DI容器实例化类,并且将对DI容器进行模拟以测试该类是否创建了预期类的实例。
依赖注入或者控制反转。
或者,对我们创建的所有对象都使用"抽象工厂"设计模式。当我们处于单元测试模式时,注入一个测试工厂,它将告诉我们要创建的内容,然后在测试工厂中包含断言代码以检查结果(控制反转)。
为了使代码尽可能整洁,请创建一个内部受保护的接口,并以生产代码为内部类来实现该接口(工厂)。将接口的静态变量类型添加为默认工厂。为工厂添加静态设置器,我们就完成了。
在测试代码中(必须位于同一程序包中,否则内部接口必须是公共的),使用声明代码和测试代码创建匿名或者内部类。然后在测试中,初始化目标类,分配(注入)测试工厂,然后运行目标类的方法。
las,我认为我犯了一个错误的问题。
我试图测试的简单工厂看起来像:
public Wrapper wrapObject(Object toWrap) { if(toWrap instanceof ClassA) { return new Wrapper((ClassA) toWrap); } else if (toWrap instanceof ClassB) { return new Wrapper((ClassB) toWrap); } // etc else { return null; } }
我在问一个问题,如何查找是否调用了" new ClassAWrapper()",因为很难在孤立的测试中获得toWrap对象。包装器(如果可以调用的话)有点奇怪,因为它使用相同的类来包装不同的对象,只是使用了不同的构造函数[1]。我怀疑如果我问的问题更好一些,我会很快收到答案的:
"我们应该模拟Object toWrap来匹配要在不同测试方法中测试的实例,并检查生成的Wrapper对象以找到返回的正确类型...希望我们很幸运,不必这样做模拟世界以创建不同的实例;-)"
我现在可以解决当前的问题,谢谢!
[1]提出是否应该重构这个问题超出了我当前问题的范围:-)
jmockit可以做到这一点。
在https://stackoverflow.com/questions/22697#93675中查看我的答案