有没有办法在Java中使用JMock模拟对象构造?
例如,如果我有这样的方法:
public Object createObject(String objectType) {
if(objectType.equals("Integer") {
return new Integer();
} else if (objectType.equals("String") {
return new String();
}
}
...有没有办法模拟测试方法中对象构造的期望?
我希望能够预期某些构造函数被调用,而不是需要额外的代码来检查类型(因为它不会像我的例子一样复杂和简单)。 / p>
所以而不是:
assertTrue(a.createObject() instanceof Integer);
我可以期待某个构造函数被调用。只是为了让它更清洁,并以更易读的方式表达实际测试内容。
请原谅这个简单的例子,我正在处理的实际问题有点复杂,但是期望会简化它。
更多背景知识:
我有一个简单的工厂方法,它创建包装器对象。被包装的对象可能需要在测试类中难以获得的参数(它是预先存在的代码),因此很难构造它们。
也许接近我真正想要的是:有没有一种方法可以一次性模拟整个类(使用CGLib),而没有指定每个方法来存根?
所以mock被包装在一个构造函数中,所以很明显可以在它上面调用方法,JMock是否能够动态模拟每个方法?
我的猜测是否定的,因为那会非常复杂。但是知道我正在咆哮错误的树也很有价值: - )
答案 0 :(得分:6)
我唯一能想到的是在工厂对象上创建create方法,而不是模拟。
但是在模拟构造函数调用方面,没有。模拟对象预先假定对象的存在,而构造函数预先假定对象不存在。至少在java中,分配和初始化一起发生。
答案 1 :(得分:4)
jmockit可以做到这一点。
中查看我的回答答案 2 :(得分:1)
我试图测试的简单工厂看起来像:
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;
}
}
我问的问题是如何查找是否调用了“新的ClassAWrapper()”,因为在隔离测试中很难获得对象toWrap。包装器(如果它甚至可以称之为)有点奇怪,因为它使用相同的类来包装不同的对象,只使用不同的构造函数[1]。我怀疑如果我更好地问这个问题,我会很快收到答案:
“你应该模拟Object toWrap以匹配你在不同测试方法中测试的实例,并检查生成的Wrapper对象以找到正确的类型返回...并希望你很幸运,你不要我必须模仿世界来创造不同的实例;-)“
我现在对即时问题有一个好的解决方案,谢谢!
[1]提出这是否应该重构的问题远远超出了我目前的问题范围: - )
答案 3 :(得分:0)
您熟悉Dependency Injection吗?
如果不是,那么你就会从了解这个概念中获益。我想马丁福勒的好老Inversion of Control Containers and the Dependency Injection pattern将作为一个很好的介绍。
使用依赖注入(DI),您将拥有一个DI容器对象,它可以为您创建各种类。然后你的对象将使用DI容器来实例化类,你将模拟DI容器来测试该类创建期望类的实例。
答案 4 :(得分:0)
依赖注入或控制反转。
或者,对您创建的所有对象使用Abstract Factory设计模式。当你处于单元测试模式时,注入一个测试工厂,它将告诉你你在创建什么,然后在测试工厂中包含断言代码来检查结果(控制反转)。
要使代码尽可能干净,请创建内部受保护的接口,使用生产代码作为内部类来实现接口(工厂)。添加初始化为默认工厂的接口的静态变量类型。为工厂添加静态设置器,你就完成了。
在您的测试代码中(必须在同一个包中,否则内部接口必须是公共的),使用断言代码和测试代码创建一个匿名或内部类。然后在测试中,初始化目标类,分配(注入)测试工厂,并运行目标类的方法。
答案 5 :(得分:-1)
我希望没有。 模拟应该模拟接口,它没有构造函数......只是方法。
在这里测试的方法似乎有些不对劲。您需要测试显式构造函数的任何原因被调用吗? 断言返回对象的类型似乎可以用于测试工厂实现。将createObject视为黑盒子..检查它返回的内容,但不要微观管理它是如何做到的。没人喜欢:))
更新更新:哎哟!绝望的绝望措施啊?如果JMock允许的话,我会感到惊讶......因为我说它适用于接口......而不是具体的类型。 所以