2015-03-01 8 views
0

Я использую mockito для тестирования общего метода. Но я получаю исключение ClassCastException, когда я запускаю junit-test.ClassCastException с использованием Mockito для общего метода

Метод испытуемый выглядит следующим образом:

public ExampleClass { 
    public <E> E randomObject(List<E> list) { 
      E e = list.get(0); 
      return e; 
    } 
} 

Ложная выглядит следующим образом:

ExampleClass exampleMock = mock(ExampleClass.class); 
List listMock = mock(List.class); 
when(exampleMock.randomObject(Matchers<List<String>any())).thenReturn("Hello"); 
when(exampleMock.randomObject(Matchers.List<Integer>any())).thenReturn(20); 

Исключение появляется на втором определении когда-метод. Похоже, метод использует только один тип, который не подлежит изменению. Но почему это так? Когда я использую общий метод с двумя разными типами в простой java, Exception не будет отображаться.

Может кто-нибудь помочь?

+0

Вы издеваетесь над ExampleClass, а также проверяете его? Ваша тестируемая система всегда должна быть реальным кодом, а не макетом, хотя вы могли бы издеваться над своими сотрудниками. (Издевательство над списком часто также является антипаттерном, хотя я бы понял, что это нужно для преодоления случайности. Часто вы можете просто передать реальную реализацию List вместо этого.) –

ответ

2

Т.Л., д-р

Split код в нескольких методов испытаний. Или цепь thenReturn API.

длинная история

Как вы, наверное, знаете Java дженериков, где реализованы с типом стиранием, что означает, что большинство из дженериков, которые вы видите в коде присутствуют только в исходном коде, а не в скомпилированный байткод ,

E.g. следующая подпись здесь

<E> E randomObject(List<E> list) 

компилируется

Object randomObject(List list) 

Это подпись, которая Mockito видит. Это идет так же, как для matchers:

when(exampleMock.randomObject(Matchers.<List<String>>any())).thenReturn("Hello"); 
when(exampleMock.randomObject(Matchers.<List<Integer>>any())).thenReturn(20); 

становится

when(exampleMock.randomObject(Matchers.any())).thenReturn("Hello"); 
when(exampleMock.randomObject(Matchers.any())).thenReturn(20); 

Mockito найти это же вызов с же согласованями. Хотя это код, который он читает, как два разных заглушки, mockito этого не знает, и может только предположить, что разработчик хочет переопределить этот первый заглушка.

Такое поведение Mockito необходим для случаев, когда по умолчанию окурок объявляется в некотором @Before методе и заглушки должны быть переопределены в некоторых @Test метода.

В этом случае код должен быть разделен или если часть более сложного сценария, заглушка должна использовать цепной API, например.

when(exampleMock.randomObject(Matchers.anyList())) 
     .thenReturn("Hello") 
     .thenReturn(20); 

_Примечание что сличитель изменился на anyList(), которые могут быть более время компиляции дружественное.

Тест может быть аннотирован @SuppressWarnings("unchecked").

+0

Спасибо за объяснение, но использование цепочки API не работает. Я получаю компилятор «Ошибка», в котором говорится, что «Метод randomObject (List ) в типе RandomBasics неприменим для аргументов (Object)» – user3637636

+0

Я писал на iPad, но я просто протестировал код с помощью java, он компилирует и работает безупречно. Но компиляторы изменились по версии Java, и, если вы используете компилятор Eclipse, у него может быть еще больше проблем. Я думаю, вы хотите использовать этот матчи вместо 'Matchers.anyList()'. (Я обновил ответ соответственно) – Brice

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