mockito를 사용하여 일반 매개 변수로 클래스를 조롱합니다
문제
일반 매개 변수로 클래스를 조롱하는 깨끗한 방법이 있습니까? 수업을 조롱해야한다고 가정 해 봅시다 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가 a 비정기 클래스, 당신은 다음 코드로 클래스를 확장하고 같은 일을 할 수 있습니다.
public class FooBar extends Foo<Bar>
{
}
그런 다음 위의 예제 중 하나를 다음 코드로 소비 할 수 있습니다.
Foo<Bar> mockFoo = mock(FooBar.class);
when(mockFoo.getValue()).thenReturn(new Bar());
a 테스트 유틸리티 방법. 두 번 이상 필요한 경우 특별히 유용합니다.
@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);
}
흥미로운 사례는 다음과 같습니다. 메소드는 일반 모음을 수신하고 동일한 기본 유형의 일반 모음을 반환합니다. 예를 들어:
Collection<? extends Assertion> map(Collection<? extends Assertion> assertions);
이 방법은 Mockito anycollection의 조합과 답변으로 조롱 할 수 있습니다.
when(mockedObject.map(anyCollectionOf(Assertion.class))).thenAnswer(
new Answer<Collection<Assertion>>() {
@Override
public Collection<Assertion> answer(InvocationOnMock invocation) throws Throwable {
return new ArrayList<Assertion>();
}
});
나는 다른 사람이 실수로 억압 된 경고를 간과 할 수 있으므로 수업이나 방법의 경고를 억제해서는 안된다는 데 동의합니다. 그러나 IMHO 단일 줄의 코드에만 영향을 미치는 경고를 억제하는 것이 절대적으로 합리적입니다.
@SuppressWarnings("unchecked")
Foo<Bar> mockFoo = mock(Foo.class);