【问题标题】:How can I determine which class a JMock mock object is mocking?如何确定 JMock 模拟对象正在模拟哪个类?
【发布时间】:2012-01-11 23:51:20
【问题描述】:

假设我有一个这样的模拟设置:

JUnit4Mockery context = new JUnit4Mockery();
MyInterface mock = context.mock(MyInterface.class);

稍后我想检查我的模拟对象以找出它正在模拟的类:

Class mockedClass = mock.??? //would return MyInterface.class

我在 JMock (2.5.1) javadocs 中没有看到任何关于如何执行此操作的明显内容 - mock 方法的签名是

<T> T mock (Class<T> typeToMock)

在以前的版本中(我看的是 1.2.0)你会直接创建一个Mock 对象,它的方法之一是

Class getMockedType()

我想要实现的是一个单元测试框架,用于在我的单元测试中使用 DI。 (我使用的是 Guice 3.0。)在测试中使用 DI 是对我正在使用的应用程序服务器/平台的限制——我正在测试的对象是 multiton 的子类,它有自己的Injector,即我要填充的内容。

我不想在每次测试中都创建一个匿名的 AbstractModule 实例,所以我正在尝试构建这样的东西(这似乎在 1.2 中可以工作):

public class MockModule extends AbstractModule {
    private Iterable<Mock> mocks;

    public MockModule(Iterable<Mock> mocks) {
        this.mocks = mocks;
    }

    protected void configure() {
        for (Mock mock : mocks) {
            bind(mock.getMockedType()).toInstance(mock);
        }
    }
}

唯一缺少的是这个问题的答案(如果有的话)。

对已接受答案的回应

这是我最终为这个用例创建的内容:

import java.lang.reflect.Proxy;
import com.google.common.collect.Lists;
import com.google.inject.AbstractModule;

@SuppressWarnings({ "rawtypes", "unchecked" })
public class MockModule extends AbstractModule {
    private final Iterable mocks;

    public MockModule(Object mock) {
        mocks = Lists.newArrayList(mock);
    }

    public MockModule(Iterable mocks) {
        this.mocks = mocks;
    }

    protected void configure() {
        for (Object mock : mocks) {
            Class superclass = mock.getClass().getSuperclass();
            if (superclass != Object.class && superclass != Proxy.class) {
                bind(superclass).toInstance(mock);
                continue;
            }
            Class[] interfaces = mock.getClass().getInterfaces();
            if (interfaces.length > 0) {
                bind(interfaces[0]).toInstance(mock);
            }
        }
    }
}

【问题讨论】:

    标签: java unit-testing guice jmock


    【解决方案1】:
    Class mockedClass = mock.getClass().getInterfaces()[0];
    System.out.println("Class is " + mockedClass.getCanonicalName());
    

    将打印:

    Interface is MyInterface
    

    可能有更强大的方法可以做到这一点,但它至少可以完成这个特定 JMock 版本的工作。

    【讨论】:

    • 谢谢!我会等着看是否有人可以建议一个更强大的版本,但这肯定会让我指向正确的方向。
    • 另一种方法可能是创建一个自定义 Imposteriser,为模拟对象添加一个额外的接口来查询它们的类。
    • 我真的很喜欢这个主意...我会研究一下。
    • 我最终使用了这个解决方案,对 class 模拟绑定进行了一些额外的检查。
    【解决方案2】:

    我不确定我是否理解您这样做的动机。 JMock 通常用于对一个对象或小对象集群进行单元测试,这意味着测试中的所有内容都是新的。 DI 通常在集成或验收测试级别开始,在执行看起来更像真实组件的东西时。

    您想通过在测试中使用 DI 来展示什么?

    【讨论】:

    • 我正在测试的对象在内部使用 Guice Injector(这是它们的子类提供的服务)。我必须用我的模拟填充注入器以测试它们。我仍然只测试对象的直接依赖关系;只是对象本身不是使用 DI 创建的,而是为了我们的理智而消耗 DI。
    • 我没有看到代码,但我的标准反应是测试试图告诉你一些关于设计的事情......
    • 我完全同意 - 问问我的团队领导我有多少抱怨。但是,这些对象的创建在运行时超出了我的控制范围,因此在我看来,完全加入 DI 是一种胜利。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多