2008-09-18 96 views
6

有没有办法在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的能够动态嘲笑出每种方法?

我的猜测是否定的,因为这会非常复杂。但知道我吠叫错了树也是有价值的:-)

+0

回答你的工厂可能有它的每种类型的可能构造(整数工厂,一个String工厂等),但,你是对自己的工厂,这是于水火之中走向过于复杂。你断言instanceof测试可能是最好的方法。 – sblundy 2008-09-18 12:48:32

回答

5

我能想到的唯一方法就是在工厂对象上创建方法,而不是模拟。

但是在嘲笑构造函数调用方面,没有。模拟对象预先假定对象的存在,而构造函数预先假定对象不存在。至少在java中分配和初始化一起发生。

-1

我希望没有。 嘲笑应该模拟接口,它没有构造函数......只是方法。

在这里测试的方法似乎有些不妥。你为什么需要测试显式构造函数被调用的任何原因?
声明返回对象的类型对于测试工厂实现似乎没有问题。把createObject当作一个黑匣子。检查它返回的内容,但不要微观管理它是如何做到的。没有人喜欢在更新:)

更新:哎哟!绝望的时候绝望的措施呃?如果JMock允许的话,我会感到惊讶...正如我所说的它在接口上工作..不是具体的类型。 所以

  • 要么尝试和花费在测试工具下让那些讨厌的输入对象的实例化'一些努力。在你的方法中自下而上。
  • 如果这是不可行的,手动测试它与断点(我知道它很烂)。然后在源文件的可见区域粘贴一个“自己承担风险的评论”并继续前进。再打一天。
+0

这是一个简单的工厂方法。问题在于工厂为其他对象创建包装(将其作为构造过程中的参数)并返回它们。我希望能够测试构造函数被调用,而不是模拟出或实例化被包装的对象。 – Grundlefleck 2008-09-18 12:33:01

+0

问题在于,工厂方法需要一个难以独立重建的对象 - 重构允许现在几乎不存在问题。虽然...嘲笑这些可能是答案... – Grundlefleck 2008-09-18 12:49:10

0

您是否知道Dependency Injection

如果不是,那么您将小心翼翼地从学习该概念中受益。我想Martin Fowler的老字号Inversion of Control Containers and the Dependency Injection pattern将作为一个很好的介绍。

借助依赖注入(DI),您将拥有一个DI容器对象,可以为您创建各种类。然后你的对象将使用DI容器来实例化类,并且你会模拟DI容器来测试该类创建期望类的实例。

0

依赖注入或控制反转。

或者,对您创建的所有对象使用抽象工厂设计模式。当你处于单元测试模式时,注入一个测试工厂,它会告诉你你在创建什么,然后在测试工厂中包含断言代码来检查结果(控制反转)。

要让代码尽可能干净,请创建一个内部受保护接口,将生产代码作为内部类实现接口(工厂)。添加一个初始化为默认工厂的接口的静态变量类型。为工厂添加静态设置器,您就完成了。

在你的测试代码中(必须在同一个包中,否则内部接口必须公开),用断言代码和测试代码创建一个匿名或内部类。然后在你的测试中,初始化目标类,分配(注入)测试工厂,并运行目标类的方法。

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; 
    } 
} 

我问这个问题如何找到,因为对象toWrap是很难获得的,如果“新ClassAWrapper()”被称为孤立的测试。而包装(如果它甚至可以被称为那个)有点奇怪,因为它使用相同的类来包装不同的对象,只是使用不同的构造函数[1]。我怀疑如果我问了一下这个问题,我很快就会收到答案:

“您应该嘲笑Object toWrap以匹配您在不同测试方法中测试的实例,并检查生成的包装器对象找到正确的类型返回...并希望你足够幸运,你不必模拟出世界来创建不同的实例;-)“

我现在有一个好的解决方案眼前的问题,谢谢!

[1]开放,这是否需要重构的问题是很好了我目前的问题:-)