【问题标题】:JMock Generic return typesJMock 通用返回类型
【发布时间】:2011-08-22 23:06:00
【问题描述】:

我正在为一个需要在自身内部创建多个集合的类编写 JMock 测试。我正在为该类提供一个工厂,该工厂将在需要时生成一个 Collection。

interface Factory
{
    <T> Collection<T> newCollection();
}

class MyClass
{
    public MyClass(Factory f)
    {
        List<ThingA> la = f.newCollection();
        List<ThingB> lb = f.newCollection();
    }
}

现在可以了,但是当使用 JMock 测试“MyClass”时,我无法模拟此返回类型重载。

Collection<ThingA> ta = new LinkedList<ThingA>();
Collection<ThingB> tb = new LinkedList<ThingB>();
Collection<ThingC> tc = new LinkedList<ThingC>();

Factory mockFactory = context.mock(Factory.class);
context.checking(new Expectations()
{
    {
        allowing(mockFactory).newCollection(); will(returnValue(ta));
        allowing(mockFactory).newCollection(); will(returnValue(tb));
        allowing(mockFactory).newCollection(); will(returnValue(tc));
    }
}
);

// All return ta
Collection<ThingA> ta2 = mockFactory.newCollection();
Collection<ThingB> tb2 = mockFactory.newCollection();
Collection<ThingC> tc2 = mockFactory.newCollection();

有没有办法让它工作?我知道我可以传入一个 ThingX 作为参数,但如果它只是为了触发类型检查以进行测试,那似乎有点毫无意义。

我当前的解决方法是添加一个序列,以便强制执行对 newCollection 的调用顺序,但我可以看到这不起作用的情况(例如泛型类型池)。

这个可以吗?

【问题讨论】:

    标签: java generics jmock


    【解决方案1】:

    类型擦除妨碍了您尝试执行的操作。正如你提到的,我只需传递一个ThingX(或ThingX.class)。不幸的是,类型擦除迫使你做那种 hacky 的事情。

    最好将您的代码分为两个域:通用感知和通用不感知,当您必须将事物从后者到前者粘合在一起时,没有办法避免做其中之一两个(用于控制事情):

    传递参数只是为了触发类型检查(如您所建议):

    Collection<ThingA> ta2 = mockFactory.newCollection(ThingA.class);
    Collection<ThingB> tb2 = mockFactory.newCollection(ThingB.class);
    Collection<ThingC> tc2 = mockFactory.newCollection(ThingC.class);
    

    或将不识别泛型的代码封装到以下方法中:a) 可识别泛型,并且 b) 具有 @SuppressWarnings("unchecked") 注释以抑制从一个域分配到另一个域时会收到的警告。

    class MockFactoryThingie
    {
       /**
        *@SuppressWarnings("unchecked")
        */
       Collection<ThingA> newThingACollection()
       { 
         return (Collection<ThingA>) ... your generic-unaware collection thing...   
       }
    }
    

    无论哪种方式都很笨拙。我们要感谢我们的 Java/JCP 霸主赐予我们这种类型擦除的宝石 :)

    【讨论】:

    • 很遗憾,Java 能够计算出正确的返回类型,因为您尝试使用引用类型来存储返回值,但 JMock 无法做到这一点。我认为我在这方面的代码都是通用的,只是 JMock 无法根据返回类型计算出要使用的通用。我不确定您的第二个选项是否有效,因为我需要知道我想要创建的所有类型并为它们创建函数,而通用方法并不关心。也许我错过了什么。
    • 哦,我确实错过了一些东西。没有注意到您手动操作了 Mock 工厂。我希望使用 JMock 意味着我可以摆脱手工制作的模拟。我想也许不是:)
    • 抱歉让你失望了,马特 :) 但是,是的,如果我要实现你正在寻找的东西,我将不得不手动摆弄模拟。这是一个崇高的目标,但不幸的是,类型擦除在 Java 中是不可能的。如果没有类型擦除,那么您所寻求的将是可能的。我能说什么?类型擦除很烂:)
    • 不是你让我失望了;你只是坏消息的带来者:)
    猜你喜欢
    • 2018-03-27
    • 2017-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-01
    • 2019-12-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多