return n"/>

关于Java:如何模拟对象构造?

关于Java:如何模拟对象构造?

How to mock object construction?

有没有一种方法可以在Java中使用JMock模拟对象构造?

例如,如果我有这样的方法:

1
2
3
4
5
6
7
public Object createObject(String objectType) {
    if(objectType.equals("Integer") {
        return new Integer();
    } else if (objectType.equals("String") {
        return new String();
    }
}

...是否有一种方法可以在测试方法中模拟对象构造的期望?

我希望能够期望某些构造函数被调用,而不必花费额外的代码来检查类型(因为它并不总是像我的示例那样复杂和简单)。

所以代替:

1
assertTrue(a.createObject() instanceof Integer);

我可以期望某些构造函数被调用。只是为了使其更加干净,并以更具可读性的方式表示实际正在测试的内容。

请原谅简单的示例,我正在处理的实际问题要复杂一些,但是有了期望会简化它。

有关更多背景信息:

我有一个简单的工厂方法,它创建包装对象。被包装的对象可能需要很难在测试类(它是预先存在的代码)中获取的参数,因此很难构造它们。

也许更接近我真正想要的是:是否有一种方法可以一口气模拟整个类(使用CGLib),而无需指定要进行存根的每个方法?

因此,模拟程序被包装在构造函数中,因此显然可以在其上调用方法,JMock是否能够动态模拟出每个方法?

我的猜测不是,因为那将非常复杂。但是知道我在吠错树也是很有价值的:-)


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

但是就模拟构造函数调用而言,没有。模拟对象以对象的存在为前提,而构造函数以对象不存在为前提。至少在Java中,分配和初始化同时发生。


jmockit可以做到这一点。

在https://stackoverflow.com/questions/22697#93675中查看我的答案


las,我觉得我问错了罪。

我试图测试的简单工厂看起来像:

1
2
3
4
5
6
7
8
9
10
11
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]提出是否应该重构这个问题超出了我当前问题的范围:-)


依赖注入或控制反转。

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

为了使您的代码尽可能整洁,请创建一个内部受保护的接口,并以生产代码作为内部类来实现该接口(您的工厂)。在接口中添加初始化为默认工厂的静态变量类型。为工厂添加静态设置器,即可完成。

在测试代??码中(必须位于同一程序包中,否则内部接口必须是公共的),使用声明代码和测试代码创建一个匿名或内部类。然后在测试中,初始化目标类,分配(注入)测试工厂,然后运行目标类的方法。


您熟悉依赖注入吗?

如果没有,那么您将自然而然地受益于对该概念的了解。我猜想马丁·福勒(Martin Fowler)的过时的控制容器反转和依赖注入模式将是一个很好的介绍。

使用依赖注入(DI),您将拥有一个DI容器对象,该对象能够为您创建各种类。然后,您的对象将使用DI容器实例化类,并且您将模拟DI容器以测试该类是否创建了预期类的实例。


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

您在此处进行测试的方法似乎不对。为什么需要测试是否调用了显式构造函数的任何原因?
断言返回对象的类型对于测试工厂实现似乎可以。将createObject视为黑匣子。.检查它返回的内容,但不进行微管理。没有人喜欢:)

更新更新:太好了!拼命的措施,拼命的时候是吗?如果JMock允许...我会感到惊讶,因为我说过它可以在接口上工作..不是具体类型。
所以

  • 要么尽力使那些讨厌的输入对象在测试工具下"可实例化"。自下而上。
  • 如果这不可行,请使用断点进行手动测试(我知道它很糟糕)。然后在源文件的可见区域中添加"自行承担风险触摸"注释,然后继续。再战一天。


推荐阅读