[java] 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가 최종 클래스 가 아닌 상황에서는 다음 코드를 사용하여 클래스를 확장하고 동일한 작업을 수행 할 수 있습니다.

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>();
         }
     });


답변