programing

Mockito를 사용하여 일반 매개 변수를 사용하여 클래스 모킹

kingscode 2022. 7. 10. 19:15
반응형

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대신 주석을 달 수 있습니다.가 있는 것은 , 더 : ) 든 、 ier 、 씬 、 씬 、 씬 、 씬 、 씬 、 doesn 、 doesn doesn doesn doesn doesn doesn doesn 。

다음은 예를 제시하겠습니다.

@RunWith(MockitoJUnitRunner.class)
public class FooTests {

    @Mock
    public Foo<Bar> fooMock;
    
    @Test
    public void testFoo() {
        when(fooMock.getValue()).thenReturn(new Bar());
    }
}

는 에서 주석이 달린 필드를 초기화합니다.

지정하는 범용 타입을 만족시키는 중간 클래스/인터페이스를 언제든지 작성할 수 있습니다.예를 들어 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);

했듯이 ' 좋다', '아주 좋다', '아주 좋다', '아주 좋다'는 좋은 사용법이 없어요.mock()&spy()안전하지 않은 제네릭 액세스 및/또는 제네릭 경고 억제 없이 직접 방법을 사용할 수 있습니다.

현재 Mockito 프로젝트(#1531)에서는 다음 명령어를 사용하기 위한 지원을 추가하기 위한 미해결 문제가 있습니다.mock()&spy()일반 경고가 없는 메서드. 않습니다.에 관한 :

.class제네릭스와는 잘 어울리지 않습니다만, 모키토에서는 할 수 있는 솔루션이 없다고 생각합니다. 할 수 요.@Mock 파라미터(JUnit5의 경우)도 사용할 수 있습니다.@Mocks) 그리고 그것이 적절한 대안이 될 것이다.따라서 이 문제를 계속 해결할 수는 있지만, 이 문제를 해결할 수는 없습니다.@Mock더 나은 API입니다.

JUnit5에서는 메서드 파라미터 또는 필드에서 @Mock을 사용하여 @ExtendWith(MockitoExtension.class)를 사용하는 것이 가장 좋다고 생각합니다.

다음 예시는 Hamcrest matchers를 사용한 예입니다.

package com.vogella.junit5;                                                                    
                                                                                               
import static org.hamcrest.MatcherAssert.assertThat;                                           
import static org.hamcrest.Matchers.hasItem;                                                   
import static org.mockito.Mockito.verify;                                                      
                                                                                               
import java.util.Arrays;                                                                       
import java.util.List;                                                                         
                                                                                               
import org.junit.jupiter.api.Test;                                                             
import org.junit.jupiter.api.extension.ExtendWith;                                             
import org.mockito.ArgumentCaptor;                                                             
import org.mockito.Captor;                                                                     
import org.mockito.Mock;                                                                       
import org.mockito.junit.jupiter.MockitoExtension;                                             
                                                                                               
@ExtendWith(MockitoExtension.class)                                                            
public class MockitoArgumentCaptureTest {                                                      
                                                                                               
                                                                                               
    @Captor                                                                                    
    private ArgumentCaptor<List<String>> captor;                                               
                                                                                               
    @Test                                                                                      
    public final void shouldContainCertainListItem(@Mock List<String> mockedList) {            
        var asList = Arrays.asList("someElement_test", "someElement");                         
        mockedList.addAll(asList);                                                             
                                                                                               
        verify(mockedList).addAll(captor.capture());                                           
        List<String> capturedArgument = captor.getValue();                                     
        assertThat(capturedArgument, hasItem("someElement"));                                  
    }                                                                                          
}                                                                                              
                                                                                              

필요한 Maven/Gradle 의존관계에 대해서는, https://www.vogella.com/tutorials/Mockito/article.html 를 참조해 주세요.

다음은 흥미로운 예입니다. 메서드는 일반 컬렉션을 수신하고 동일한 기본 유형의 일반 컬렉션을 반환합니다.예를 들어 다음과 같습니다.

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

JUnit5: 사용@ExtendWith(MockitoExtension.class)테스트 클래스에 다음 필드를 추가합니다.

@Mock
Foo<Bar> barMock;

왜 스파이를 사용하지 않는가?

var mock = spy(new Foo<Bar>());
when(mockFoo.getValue()).thenReturn(new Bar());

언급URL : https://stackoverflow.com/questions/1652692/using-mockito-to-mock-classes-with-generic-parameters

반응형