2011-12-23 5 views
0


Вот моя проблема:фиктивный метод с общим типом возвращаемого с Mockito

public interface Containter extends ModelElement{ 
    List<? extends ModelElement> getChildren(); 
} 

Есть несколько классов, реализующих Containter, и я хочу, чтобы насмехаться над ними:

public class MockMama { 
    public static <T extends Containter, Y extends ModelElement> T bornContainer(Class<T> clazz, Y ... children) { 
      T container = mock(clazz); 
      when(container.getChildren()).thenReturn(Arrays.asList(children)); 
      return container; 
    } 
} 

Но это Безразлично Не работай. Eclipse говорит: «Метод thenReturn (List) в типе OngoingStubbing> не применим для аргументов (List)». Я также попытался передать локально объявленную переменную типа List <? extends ModelElement> на thenReturn, но это тоже не помогло.
Любая помощь очень ценится и приветствуется :)

+0

Хорошо, это может быть исправлено путем введения дополнительных локальных переменных, таких как Список list = Arrays.asList (дети); когда (container.getChildren()). ThenReturn (list); Есть ли способ сделать это, не вызывая предупреждения типа типа? – user656449

ответ

2

Ваша проблема в том, что нет гарантии, что тип, возвращаемый getChildren(), соответствует типу аргумента varargs вашему методу bornContainer. Поэтому компилятор прав, чтобы жаловаться на это. Использование промежуточной локальной переменной действительно превращает ошибку компилятора в потенциальную проблему времени выполнения.

Мне кажется, что ваш «Контейнер» должен действительно быть родовым классом, потому что его поведение зависит от типа, который находится в списке, который возвращает getChildren(). Взгляните на мою переписку с вашим примером. У этого нет компиляционных ошибок или предупреждений.

public interface Containter<Z extends ModelElement> extends ModelElement{  
    List<Z> getChildren(); 
} 

public class MockMama {  
    public static <Y extends ModelElement, T extends Containter<Y>> T bornContainer(Class<T> clazz, Y ... children) {    
     T container = mock(clazz);    
     when(container.getChildren()).thenReturn(Arrays.asList(children));    
     return container;  
    } 
} 

Надеюсь, это поможет.

+0

Благодарим вас за ответ. Но контейнер действительно не может быть общим - он должен иметь возможность возвращать ModelElements любого типа. Также мне жаль, в вопросе была опечатка - не должно быть Z2ModelElements, все emelents - это просто ModelElements. Таким образом, оба метода getChildren и методов контейнера - Y расширяет ModelElement, почему должны появляться какие-либо дополнительные гарантии? – user656449

+0

Поскольку 'Y', возвращаемый' getChildren', не обязательно совпадает с 'Y', переданным в 'bornContainer'; и компилятор пытается защитить вас от вас самих. Однако, если эти методы должны иметь дело с любым типом «ModelElement», возможно, вы можете полностью удалить «Y», то есть возвращаемый тип 'getChildren' может быть« List », а второй параметр 'bornContainer' может быть просто' ModelElement ... ' –

+0

Ok. Кажется, я понял. Спасибо. – user656449

0

Обычно в тестах вы можете игнорировать непроверенные или необработанные предупреждения типа. Поэтому, как правило, безопасно аннотировать ваш тест с помощью директивы компилятора, такой как @SupressWarning("unchecked").

+0

ну да, его можно подавить, но я не могу понять, почему исходный код не компилируется. И это заставляет меня нервничать :) Я чувствую, что это какая-то дерьмо. «Вы можете сделать x, за исключением случая y, если y не делает z, и в этом случае вы можете, если ...» Кен Арнольд рассказывает о http: // weblogs .java.net/blog/arnold/archive/2005/06/generics_consid.html – user656449

Смежные вопросы