1. 개요

모의 프레임 워크를 사용한 단위 테스트는 오랫동안 유용한 관행으로 인식되어 왔으며 특히 Mockito 프레임 워크가 최근 몇 년 동안이 시장을 지배했습니다.

그리고 적절한 코드 디자인을 촉진하고 공용 API를 단순하게 만들기 위해 일부 원하는 기능을 의도적으로 제외했습니다. 그러나 어떤 경우에는 이러한 단점으로 인해 테스터가 모의 생성을 가능하게 만들기 위해 번거로운 코드를 작성해야합니다.

여기에서 PowerMock 프레임 워크가 작동합니다.

PowerMockito 는 Mockito를 지원하는 PowerMock의 확장 API입니다. Mockito의 문제를 극복하는 간단한 방법으로 Java Reflection API로 작업 할 수있는 기능을 제공합니다 (예 : 최종, 정적 또는 개인 메서드 모의 기능 부족).

이 예제은 PowerMockito API에 대한 소개와 테스트에서 어떻게 적용되는지 설명합니다.

2. PowerMockito로 테스트 준비하기

Mockito에 대한 PowerMock 지원을 통합하는 첫 번째 단계는 Maven POM 파일에 다음 두 가지 의존성을 포함하는 것입니다.

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>1.6.4</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito</artifactId>
    <version>1.6.4</version>
    <scope>test</scope>
</dependency>

다음으로 다음 두 어노테이션을 적용 하여 PowerMockito 작업을위한 테스트 케이스를 준비해야합니다 .

@RunWith(PowerMockRunner.class)
@PrepareForTest(fullyQualifiedNames = "com.baeldung.powermockito.introduction.*")

@PrepareForTest 어노테이션 fullyQualifiedNames 요소는 우리가 조롱하려는 유형의 정규화 된 이름 배열을 나타냅니다. 이 경우 와일드 카드가있는 패키지 이름을 사용하여 PowerMockito 에게 com.baeldung.powermockito.introduction 패키지 내의 모든 유형 을 조롱 하도록 준비하도록 지시 합니다.

이제 PowerMockito 의 힘을 활용할 준비가되었습니다 .

3. 조롱 생성자와 최종 메서드

이 섹션에서는 new 연산자 로 클래스를 인스턴스화 할 때 실제 인스턴스 대신 모의 인스턴스를 가져 오는 방법을 보여준 다음 해당 개체를 사용하여 최종 메서드를 모의합니다. 생성자와 최종 메서드가 모의 될 공동 작업 클래스는 다음과 같이 정의됩니다.

public class CollaboratorWithFinalMethods {
    public final String helloMethod() {
        return "Hello World!";
    }
}

먼저 PowerMockito API를 사용하여 모의 객체를 만듭니다 .

CollaboratorWithFinalMethods mock = mock(CollaboratorWithFinalMethods.class);

다음으로, 해당 클래스의 인수가없는 생성자가 호출 될 때마다 실제 인스턴스가 아닌 모의 인스턴스가 반환되어야한다는 기대치를 설정합니다.

whenNew(CollaboratorWithFinalMethods.class).withNoArguments().thenReturn(mock);

기본 생성자를 사용하여 CollaboratorWithFinalMethods 클래스를 인스턴스화 한 다음 PowerMock의 동작을 확인 하여이 생성 모의 작동 방식을 살펴 보겠습니다 .

CollaboratorWithFinalMethods collaborator = new CollaboratorWithFinalMethods();
verifyNew(CollaboratorWithFinalMethods.class).withNoArguments();

다음 단계에서는 최종 방법에 대한 기대치를 설정합니다.

when(collaborator.helloMethod()).thenReturn("Hello Baeldung!");

그런 다음이 메서드가 실행됩니다.

String welcome = collaborator.helloMethod();

다음 어설 션은 helloMethod 메서드가 collaborator 객체에서 호출되었음을 확인 하고 모의 기대에 의해 설정된 값을 반환합니다.

Mockito.verify(collaborator).helloMethod();
assertEquals("Hello Baeldung!", welcome);

객체 내부의 모든 최종 메서드가 아닌 특정 최종 메서드를 모의하려면 Mockito.spy (T object) 메서드가 유용 할 수 있습니다. 이것은 섹션 5에 설명되어 있습니다.

4. 정적 메서드 조롱

CollaboratorWithStaticMethods 라는 클래스의 정적 메서드를 조롱한다고 가정합니다 . 이 클래스는 다음과 같이 선언됩니다.

public class CollaboratorWithStaticMethods {
    public static String firstMethod(String name) {
        return "Hello " + name + " !";
    }

    public static String secondMethod() {
        return "Hello no one!";
    }

    public static String thirdMethod() {
        return "Hello no one again!";
    }
}

이러한 정적 메서드를 모의하려면 PowerMockito API를 사용하여 둘러싸는 클래스를 등록해야합니다 .

mockStatic(CollaboratorWithStaticMethods.class);

또는 Mockito.spy (Class <T> class) 메서드를 사용하여 다음 섹션에서 설명하는 것처럼 특정 항목을 모의 할 수 있습니다.

다음으로, 호출 될 때 메서드가 반환해야하는 값을 정의하도록 기대치를 설정할 수 있습니다.

when(CollaboratorWithStaticMethods.firstMethod(Mockito.anyString()))
  .thenReturn("Hello Baeldung!");
when(CollaboratorWithStaticMethods.secondMethod()).thenReturn("Nothing special");

또는 thirdMethod 메서드를 호출 할 때 예외가 throw되도록 설정할 수 있습니다 .

doThrow(new RuntimeException()).when(CollaboratorWithStaticMethods.class);
CollaboratorWithStaticMethods.thirdMethod();

이제 처음 두 가지 방법을 실행할 때입니다.

String firstWelcome = CollaboratorWithStaticMethods.firstMethod("Whoever");
String secondWelcome = CollaboratorWithStaticMethods.firstMethod("Whatever");

실제 클래스의 멤버를 호출하는 대신 위의 호출이 모의 메서드에 위임됩니다. 다음 주장은 모의가 효과가 있음을 증명합니다.

assertEquals("Hello Baeldung!", firstWelcome);
assertEquals("Hello Baeldung!", secondWelcome);

또한 메소드가 호출 된 횟수를 포함하여 모의 메소드의 동작을 확인할 수 있습니다. 이 경우 firstMethod 는 두 번 호출되었지만 secondMethod다음과 같은 일 이 없습니다.

verifyStatic(Mockito.times(2));
CollaboratorWithStaticMethods.firstMethod(Mockito.anyString());
        
verifyStatic(Mockito.never());
CollaboratorWithStaticMethods.secondMethod();

참고 : verifyStatic에 대한 정적 방법을 검증하기 직전 방법은 호출해야합니다 PowerMockito가 연속 메소드 호출이 검증 될 필요가 무엇을 알고.

마지막으로, 정적 thirdMethod 메서드는 이전에 mock에서 선언 된대로 RuntimeExceptionthrow해야합니다 . @Test 어노테이션 예상 요소에 의해 유효성이 검사됩니다 .

@Test(expected = RuntimeException.class)
public void givenStaticMethods_whenUsingPowerMockito_thenCorrect() {
    // other methods   
       
    CollaboratorWithStaticMethods.thirdMethod();
}

5. 부분 조롱

전체 클래스를 조롱하는 대신 PowerMockito API는 spy 메서드를 사용 하여 클래스의 일부를 조롱 할 수 있습니다 . 다음 클래스는 부분 모의에 대한 PowerMock 지원을 설명하기 위해 공동 작업자로 사용됩니다.

public class CollaboratorForPartialMocking {
    public static String staticMethod() {
        return "Hello Baeldung!";
    }

    public final String finalMethod() {
        return "Hello Baeldung!";
    }

    private String privateMethod() {
        return "Hello Baeldung!";
    }

    public String privateMethodCaller() {
        return privateMethod() + " Welcome to the Java world.";
    }
}

위의 클래스 정의에서 staticMethod 라는 이름의 정적 메서드를 조롱하는 것으로 시작하겠습니다 . 먼저 PowerMockito API를 사용하여 CollaboratorForPartialMocking 클래스 를 부분적으로 모의 하고 정적 메서드에 대한 기대치를 설정합니다.

spy(CollaboratorForPartialMocking.class);
when(CollaboratorForPartialMocking.staticMethod()).thenReturn("I am a static mock method.");

그런 다음 정적 메서드가 실행됩니다.

returnValue = CollaboratorForPartialMocking.staticMethod();

조롱 동작은 다음과 같이 확인됩니다.

verifyStatic();
CollaboratorForPartialMocking.staticMethod();

다음 어설 션은 반환 값을 기대 값과 비교하여 모의 메서드가 실제로 호출되었음을 확인합니다.

assertEquals("I am a static mock method.", returnValue);

이제 최종 및 개인 방법으로 이동할 때입니다. 이러한 메서드의 부분적인 조롱을 설명하려면 클래스를 인스턴스화하고 PowerMockito API에 스파이 하도록 지시 해야합니다.

CollaboratorForPartialMocking collaborator = new CollaboratorForPartialMocking();
CollaboratorForPartialMocking mock = spy(collaborator);

위에서 만든 개체는 최종 및 개인 메서드의 조롱을 보여주는 데 사용됩니다. 이제 기대치를 설정하고 메서드를 호출하여 최종 메서드를 처리합니다.

when(mock.finalMethod()).thenReturn("I am a final mock method.");
returnValue = mock.finalMethod();

해당 메서드를 부분적으로 조롱하는 동작이 입증되었습니다.

Mockito.verify(mock).finalMethod();

테스트는 finalMethod 메서드 를 호출 하면 예상과 일치하는 값이 반환 되는지 확인합니다 .

assertEquals("I am a final mock method.", returnValue);

private 메서드에도 유사한 프로세스가 적용됩니다. 주요 차이점은 테스트 케이스에서이 메소드를 직접 호출 할 수 없다는 것입니다. 기본적으로 private 메서드는 같은 클래스의 다른 메서드에 의해 호출됩니다. 에서 CollaboratorForPartialMocking의 클래스는 privateMethod 방법은 호출 할 것입니다 privateMethodCaller의 방법과 우리가 대리인으로 후자를 사용합니다. 기대와 호출부터 시작하겠습니다.

when(mock, "privateMethod").thenReturn("I am a private mock method.");
returnValue = mock.privateMethodCaller();

private 메서드의 조롱이 확인되었습니다.

verifyPrivate(mock).invoke("privateMethod");

다음 테스트는 private 메서드 호출의 반환 값이 예상과 동일한 지 확인합니다.

assertEquals("I am a private mock method. Welcome to the Java world.", returnValue);

6. 결론

이 사용방법(예제)는 PowerMockito API에 대한 소개를 제공하여 개발자가 Mockito 프레임 워크를 사용할 때 발생하는 일부 문제를 해결하는 데 사용하는 방법을 보여줍니다.

이러한 예제 및 코드 스 니펫의 구현은 링크 된 GitHub 프로젝트 에서 찾을 수 있습니다 .