JMock Универсальные возвращаемые типы - PullRequest
1 голос
/ 22 августа 2011

Я пишу тест 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 Ответ

1 голос
/ 22 августа 2011

Тип стирание мешает тому, что вы пытаетесь сделать.Я бы просто передал 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);

, либо инкапсулировать код, не связанный с универсальным кодом, в методы, которыеа) совместимы с генериками и б) имеют аннотацию @SuppressWarnings("unchecked") для подавления предупреждения, которое вы получите при назначении из одного домена в другой.

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

Любой способ неуклюж.Мы должны поблагодарить наших повелителей Java / JCP за то, что они дали нам этот драгоценный камень типа erasure:)

...