티스토리 뷰

특정 클래스에 대해  Testcase 를 작성할 때, private method 에 대한 mock 처리가 필요할 때가 있다.

예를 들면 private method 에서 외부 시스템과 연동을 하고 있다거나 하는 등 테스트하려는 목적을 벗어난 경우가 있을 수 있다.
이 때 특정 method 만 mock 처리를 하면 간단히 나머지 부분을 테스트 할 수 있다.

샘플 코드를 통해 알아보자.

DataService 라는 클래스가 있다고 가정하자.

public class DataService {
    public boolean replaceData(final String dataId, final String data) {
        return modifyData(dataId, data);
    }

    public boolean deleteData(final String dataId) {
        return modifyData(dataId, null);
    }

    private boolean modifyData(final String dataId, final String data) {
        /**
         * 구현내용
         */
        return true;
    }
}

modifyData 라는 private method 를 갖고 있다.
보통 unit test 를 하더라도 private method 를 포함해서 Testcase 를 작성하곤 하지만, 여기서는 private method 를 mock 처리 해 보자.

먼저 private method 를 mock 처리하기 위해 powermockito 를 사용하기로 하겠다.
(다른 라이브러리도 있는지 모르겠지만, 그냥 알고 있는 powermockito 를 사용했다.)
아래와 같이 pom.xml 에 dependency 를 추가하였다. 편의상 Maven 을 사용했지만, 라이브러리를 classpath 에 추가해주면 된다.

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
    </dependency>
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-module-junit4</artifactId>
        <version>1.5.6</version>
    </dependency>
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-api-mockito</artifactId>
        <version>1.6.2</version>
    </dependency>
</dependencies>


@RunWith(PowerMockRunner.class)
@PrepareForTest({DataService.class})
public class DataServiceTest {
    private DataService dataService;

    @Before
    public void setUp() throws Exception {
        dataService = PowerMockito.spy(new DataService());
    }

    @Test
    public void PrivateMethod_Mock처리() throws Exception {
        PowerMockito.when(dataService"modifyData"anyString(), anyString()).thenReturn(false);

        boolean flag = dataService.replaceData("dataId""data");

        assertFalse(flag);
    }
}

별도의 mock 처리를 하지 않았다면 해당 Testcase 는 실패해야 한다.
그 이유는 modifyData 함수는 true 를 반환하도록 되어 있으므로, replaceData() 의 결과는 true 가 되기 때문이다.
여기에서는 mock 처리를 통해 false 가 반환되도록 변경하였다.
그래서 Testcase 는 성공한다.





추가적으로 junit-4.12 버전을 사용하면 아래와 같은 오류가 발생할 수 있다.
4.12 버전에서 뭔가 변경이 있는 듯 하다.(자세히는 잘 모르겠다.)
4.11 버전으로 변경하면 정상적으로 수행이 된다.

  • junit-4.11
  • powermock-module-junit4 1.5.6
  • powermock-api-mockito 1.6.2

org.powermock.reflect.exceptions.FieldNotFoundException: Field 'fTestClass' was not found in class org.junit.internal.runners.MethodValidator.     at org.powermock.reflect.internal.WhiteboxImpl.getInternalState(WhiteboxImpl.java:581)     at org.powermock.reflect.Whitebox.getInternalState(Whitebox.java:308)     at org.powermock.modules.junit4.internal.impl.testcaseworkaround.PowerMockJUnit4MethodValidator.validateTestMethods(PowerMockJUnit4MethodValidator.java:79)     at org.powermock.modules.junit4.internal.impl.testcaseworkaround.PowerMockJUnit4MethodValidator.validateInstanceMethods(PowerMockJUnit4MethodValidator.java:49)     at org.junit.internal.runners.MethodValidator.validateMethodsForDefaultRunner(MethodValidator.java:51)     at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.validate(PowerMockJUnit44RunnerDelegateImpl.java:108)     at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.<init>(PowerMockJUnit44RunnerDelegateImpl.java:70)     at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl.<init>(PowerMockJUnit47RunnerDelegateImpl.java:42)     at org.powermock.modules.junit4.internal.impl.PowerMockJUnit49RunnerDelegateImpl.<init>(PowerMockJUnit49RunnerDelegateImpl.java:25)     at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)     at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)     at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)     at java.lang.reflect.Constructor.newInstance(Constructor.java:408)     at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:149)     at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:39)     at org.powermock.tests.utils.impl.AbstractTestSuiteChunkerImpl.createTestDelegators(AbstractTestSuiteChunkerImpl.java:218)     at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.<init>(JUnit4TestSuiteChunkerImpl.java:59)     at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.<init>(AbstractCommonPowerMockRunner.java:32)     at org.powermock.modules.junit4.PowerMockRunner.<init>(PowerMockRunner.java:33)     at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)     at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)     at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)     at java.lang.reflect.Constructor.newInstance(Constructor.java:408)     at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)     at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)     at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)     at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)     at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)     at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)     at org.junit.internal.requests.FilterRequest.getRunner(FilterRequest.java:36)     at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:41)     at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)     at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)     at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)


참고자료

'Programing > Java' 카테고리의 다른 글

Java Static 과 Spring Singleton 의 차이  (0) 2016.01.20
slf4j 란?  (0) 2016.01.20
javax.net.ssl.SSLProtocolException 해결책  (0) 2015.12.31
java.io.InvalidClassException  (0) 2015.07.15
Serializable 과 transient  (0) 2015.06.29
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함