일반 매개 변수로 클래스를 조롱하는 깨끗한 방법이 있습니까? 내가 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);
}
답변
클래스 또는 메서드에서 실수로 억제 된 다른 경고를 간과 할 수 있으므로 경고를 억제해서는 안된다는 데 동의합니다. 그러나 IMHO 한 줄의 코드에만 영향을주는 경고를 표시하지 않는 것이 합리적입니다.
@SuppressWarnings("unchecked")
Foo<Bar> mockFoo = mock(Foo.class);
답변
흥미로운 경우가있다 : 메소드는 제네릭 콜렉션을 수신하고 동일한 기본 유형의 제네릭 콜렉션을 리턴합니다. 예를 들면 다음과 같습니다.
Collection<? extends Assertion> map(Collection<? extends Assertion> assertions);
이 메소드는 Mockito anyCollectionOf matcher와 Answer를 조합하여 조롱 할 수 있습니다.
when(mockedObject.map(anyCollectionOf(Assertion.class))).thenAnswer(
new Answer<Collection<Assertion>>() {
@Override
public Collection<Assertion> answer(InvocationOnMock invocation) throws Throwable {
return new ArrayList<Assertion>();
}
});