특정 클래스에 대해 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)
|
참고자료
- https://code.google.com/p/powermock/wiki/MockPrivate
- https://code.google.com/p/powermock/issues/detail?id=531
'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 |