2011-08-22 93 views
1

我正在为需要在其内部创建多个集合的类编写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

类型擦除正在影响您正在尝试做的事情。正如你所提到的,我只是通过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); 

或封装泛型不知道代码到方法,这是一个)泛型感知,并b)有一个@SuppressWarnings("unchecked")注释来抑制从一个域到另一个域的分配时得到的警告。

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

无论哪种方式都很笨重。我们得感谢我们的Java/JCP霸主,向我们赠送这个类型擦除的宝石:)

+0

这真是一种遗憾,Java能够计算出正确的返回类型,因为您尝试使用的参考类型来存储返回,但JMock不能这样做。我认为我在这方面的代码都是通用的,它只是JMock不能根据返回类型制定出使用的泛型。我不确定你的第二个选项是否可行,因为我需要知道我想创建的所有类型并为它们创建函数,而通用方法并不在意。也许我错过了什么。 –

+1

哦,我确实错过了一些东西。没有注意到你是在模拟工厂里工作。我希望使用JMock意味着我可以摆脱手工制作模仿。我想也许不是:) –

+0

对不起,让你失望马特:)但是,是的,如果我要实现你正在寻找的东西,我将不得不手动摆弄嘲笑。这是一个崇高的目标,但不幸的是,类型擦除使得在Java中不可能。如果没有类型擦除,那么你所寻求的将是可能的。我能说什么?类型擦除吸吮:) –