2015-06-05 1 views
5

EDIT: Я, наконец, создал issue на Mockito GitHub проекте.Mockito returnsFirstArg() не работает с общим первым аргом

Я пытаюсь издеваться набранный метод getNameElement интерфейса RoomGeneralService возвратить первый ARG, используя Mockito AdditionalAnswers.returnsFirstArg функциональность:

Интерфейс издеваться:

interface PrimaryKeyElement<T> { 
    public String getNameElement(T primaryKey); 
} 

interface RoomGeneralService extends PrimaryKeyElement<String> { 
    // ... 
} 

Мой тест (обратите внимание на импорт)

import static org.mockito.AdditionalAnswers.returnsFirstArg; 
import static org.mockito.Matchers.any; 
import static org.mockito.Matchers.anyString; 
import static org.mockito.Mockito.when; 

@RunWith(PowerMockRunner.class) 
public class SampleTest { 

    @Mock 
    RoomGeneralService roomGeneralService; 

    @Test 
    public void testFoo() throws Exception { 
     when(roomGeneralService.getNameElement(anyString())).thenAnswer(returnsFirstArg()); 
     //... 
    } 
} 

Кроме того, я попытался с другими комбинациями, но без успеха до сих пор:

when(roomGeneralService.getNameElement(Matchers.<String>any())).thenAnswer(returnsFirstArg()); 
doAnswer(returnsFirstArg()).when(roomGeneralService.getNameElement(anyString())); 
doReturn(returnsFirstArg()).when(roomGeneralService.getNameElement(anyString())); 

Ошибка получил:

Причиной этой ошибки может быть: 1. хотел аргумент неверно. 2. Ответ используется для неправильного взаимодействия.

Положение разыскиваемого аргумента 0 и возможный аргумент индексов для этого метода являются: [0] Объект

Обход:

Я знаю, что я могу создать свой собственный ответ, и на самом деле он работает нормально, если вместо использования returnFirstArg() Я делаю что-то вроде этого:

when(roomGeneralService.getNameElement(anyString())).thenAnswer(new Answer<String>() { 
    @Override 
    public String answer(InvocationOnMock invocation) throws Throwable { 
     return (String) invocation.getArguments()[0]; 
    } 
}); 

Но я бы использовал returnFirstArg(), как и в остальных моих тестах (тесты выглядят чище), а также насмешка работает нормально, если метод getNameElement получит String вместо T arg.

Спасибо за помощь.

ответ

0

я наконец-то решил открыть вопрос (#1071) на GitHub проекта Mockito и она была исправлена ​​в версии 2.8.29 (см официальные changelog) Благодаря команде Mockito решить ее так быстро!

Цитирование @ChristianSchwarz, здесь проблема объяснения:

Mockito проверяет, является ли аргумент типа совместим с типом возвращаемого , чтобы злоупотребление Ot к API, как только Возможное видимы. В этом случае объект типа аргумента выводится из общего типа T из-за стирания типа . Так как Object не является подтипом String Mockito, то выбрасывает исключение, которое вы видите.

Решение может быть устранено путем установления аргумента типа фактического аргумента-аргумента . В случае, если аргумент-тип является примитивным или , аргумент arg является нулевым. Mockito должен отступить и использовать тип, предоставляемый сигнатурой метода .

1

Кажется, Mockito недостаточно умен, чтобы вывести, что тип параметра будет привязан к String в параметризованном подинтерфейсе.

Вы можете переопределить метод в подинтерфейсе

interface RoomGeneralService extends PrimaryKeyElement<String> { 
    @Override 
    public String getNameElement(String primaryKey); 
} 

Mockito не придется гадать. Он будет ясно видеть String как тип параметра обрезанного метода.

+0

Прежде всего, спасибо, что ответили. К сожалению, переопределение метода не является вариантом для проекта. Если Мокито не может этого сделать, я предпочитаю продолжить обходной путь. – troig

+0

@troig Вы не контролируете исходный код этих интерфейсов? –

+0

Нет, это проблема. Спасибо за ваш подход. – troig