Ответ 1
Я думаю, вам нужно разыграть его, но это не должно быть слишком плохо:
Foo<Bar> mockFoo = (Foo<Bar>) mock(Foo.class);
when(mockFoo.getValue()).thenReturn(new Bar());
Есть ли чистый метод издевательства над классом с общими параметрами? Скажем, я должен высмеять класс Foo<T>
, который мне нужно передать в метод, который ожидает Foo<Bar>
. Я могу сделать следующее достаточно легко:
Foo mockFoo = mock(Foo.class);
when(mockFoo.getValue).thenReturn(new Bar());
Предполагая, что getValue()
возвращает общий тип T
. Но это будет иметь котят, когда я позже передам его методу, ожидающему Foo<Bar>
. Является ли это единственным средством для этого?
Я думаю, вам нужно разыграть его, но это не должно быть слишком плохо:
Foo<Bar> mockFoo = (Foo<Bar>) mock(Foo.class);
when(mockFoo.getValue()).thenReturn(new Bar());
Другим способом решения этой проблемы является использование аннотации @Mock
.
Не работает во всех случаях, но выглядит намного сексуальнее:)
Вот пример:
@RunWith(MockitoJUnitRunner.class)
public class FooTests {
@Mock
public Foo<Bar> fooMock;
@Test
public void testFoo() {
when(fooMock.getValue()).thenReturn(new Bar());
}
}
MockitoJUnitRunner
инициализирует поля, аннотированные с помощью @Mock
.
Вы всегда можете создать промежуточный класс/интерфейс, который будет удовлетворять универсальному типу, который вы хотите указать. Например, если Foo был интерфейсом, вы можете создать следующий интерфейс в своем тестовом классе.
private interface FooBar extends Foo<Bar>
{
}
В ситуациях, когда Foo не является финальным классом, вы можете просто расширить класс следующим кодом и сделать то же самое:
public class FooBar extends Foo<Bar>
{
}
Тогда вы можете использовать любой из приведенных выше примеров с помощью следующего кода:
Foo<Bar> mockFoo = mock(FooBar.class);
when(mockFoo.getValue()).thenReturn(new Bar());
Создайте метод тестовой утилиты. Особенно полезно, если вам это нужно более одного раза.
@Test
public void testMyTest() {
// ...
Foo<Bar> mockFooBar = mockFoo();
when(mockFooBar.getValue).thenReturn(new Bar());
Foo<Baz> mockFooBaz = mockFoo();
when(mockFooBaz.getValue).thenReturn(new Baz());
Foo<Qux> mockFooQux = mockFoo();
when(mockFooQux.getValue).thenReturn(new Qux());
// ...
}
@SuppressWarnings("unchecked") // still needed :( but just once :)
private <T> Foo<T> mockFoo() {
return mock(Foo.class);
}
Я согласен с тем, что не следует подавлять предупреждения в классах или методах, поскольку можно пропустить другие, случайно подавленные предупреждения. Но ИМХО абсолютно разумно подавить предупреждение, которое затрагивает только одну строку кода.
@SuppressWarnings("unchecked")
Foo<Bar> mockFoo = mock(Foo.class);
Вот интересный случай: метод получает общий набор и возвращает общий набор того же базового типа. Например:
Collection<? extends Assertion> map(Collection<? extends Assertion> assertions);
Этот метод можно высмеять с помощью комбинации Mockito anyCollectionOf и ответа.
when(mockedObject.map(anyCollectionOf(Assertion.class))).thenAnswer(
new Answer<Collection<Assertion>>() {
@Override
public Collection<Assertion> answer(InvocationOnMock invocation) throws Throwable {
return new ArrayList<Assertion>();
}
});