JMock通用返回类型

时间:2011-08-22 10:42:22

标签: java generics jmock

我正在为一个需要在其自身内创建多个集合的类编写JMock测试。我正在为班级提供一个工厂,在需要时会生成一个收藏。

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的调用顺序,但我可以看到这种情况不起作用的情况(比如通用类型的汇集)。

可以这样做吗?

1 个答案:

答案 0 :(得分: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领主给我们这个类型擦除的宝石:)