我正在为一个需要在其自身内创建多个集合的类编写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的调用顺序,但我可以看到这种情况不起作用的情况(比如通用类型的汇集)。
可以这样做吗?
答案 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领主给我们这个类型擦除的宝石:)