2016-09-06 3 views
1

PowerMockito를 사용하여 IOException을 던지는 정적 클래스를 모의하려고합니다. 내 패키지에 JUnit 4.12와 PowerMockMockito 1.6.3을 사용하고 있습니다. 그러나 클래스 정의 위에 놓아야하는 "@RunWith (PowerMockRunner.class)"주석으로 인해 "initializationError"가 발생합니다. 이것은 테스트 클래스가 비어있는 경우에도 발생합니다. 여기 PowerMockRunner 초기화 오류

오류의 스택 추적입니다 : 문제를 해결하기

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:97) 
at org.powermock.modules.junit4.internal.impl.testcaseworkaround.PowerMockJUnit4MethodValidator.validateInstanceMethods(PowerMockJUnit4MethodValidator.java:67) 
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 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:423) 
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:156) 
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:40) 
at org.powermock.tests.utils.impl.AbstractTestSuiteChunkerImpl.createTestDelegators(AbstractTestSuiteChunkerImpl.java:244) 
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.<init>(JUnit4TestSuiteChunkerImpl.java:61) 
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.<init>(AbstractCommonPowerMockRunner.java:32) 
at org.powermock.modules.junit4.PowerMockRunner.<init>(PowerMockRunner.java:34) 
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:423) 
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.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.<init>(JUnit4TestReference.java:33) 
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestClassReference.<init>(JUnit4TestClassReference.java:25) 
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:48) 
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:38) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:444) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) 

내 시도는 PowerMockito가 1.6로 업데이트 후 비슷한 문제가 해결 된 this 하나, 같은 여러 가지 이전 SO 질문에 저를 주도하고있다 .1. 불행히도 그것은별로 도움이되지 못했습니다.

PowerMockito를 처음 사용하기 때문에 가이드에 언급 된 내용이 너무 분명한 것 같습니다. 이 문제를 어떻게 해결할 수 있을지에 대한 아이디어가 있습니까? 미리 감사드립니다.

+1

내 대답으로 잘라내 지 못할 수도 있고 여기에 "진짜"대답이없는 경우 (자주 일어나는 일) ... https://groups.google.com/forum에서 시도해 볼 수 있습니다./#! forum/powermock - PM 개발자가 읽는 곳입니다. – GhostCat

+0

시험 수업을 업데이트 할 수 있습니까 – kuhajeyan

답변

2

모든 것이 코드 인 경우 매우 미묘한 해결책은 다음과 같습니다. PowerMock과 이러한 종류의 문제를 완전히 피하십시오. 그 대신에 정적 인이 좋은 OO 디자인의 이상으로 받아 들여진다 - ​​그것은 클래스의 직접적인, 하드 커플 링으로 이어집니다.

따라서 테스트하기 쉽도록 큰 Powermock 해머가 필요한 테스트하기 어려운 코드를 작성하는 대신 정적 인 코드를 피하는 코드를 제안하십시오. 따라서 Powermock을 필요로하지 않고 테스트 할 수 있습니다.

짧은 이야기 : 테스트 할 수있는 코드 작성에 대해 배우십시오 (예 : [동영상] [1] 듣기). 그리고 Powermock 방의 문을 닫으십시오. 그리고 그 때 정적 너는 소유하지 않는 외부 코드에 살고있다; 여전히 주위에 래퍼를 넣고 직접적인 종속성을 피할 수 있습니다.

편집 : 물론, 아파치 평민과 같은 중앙 일을 해결하려면 복잡하지만, 여전히, 당신은 항상과 같이 할 수 있습니다 : 당신이 전달할 수

class TheStaticThing { 
    public static Whatever doSomething(Somethin els) throws StupidException { ... 

및 "인터페이스"를이 :

interface TheStaticThingFunctionality { 
    public static Whatever doSomething(Somethin els) throws StupidException; 

그런 다음 당신은 간단한

class TheStaticThingImpl implements TheStaticThingFunctionality { 
    @Override 
    public Whatever doSomething(Somethin els) throws StupidException { 
    return TheStaticThing.doSomething(els); 
    } 
이 0

그리고, 지금 클라이언트 클래스 내에서 : 당신의 클라이언트 클래스로 TheStaticThingFunctionality의 오버 헤드를 최소화

  • 패스 조롱 인스턴스가 기존의 정적 인 방법을 사용하여

    1. 킵을 :

      class Client { 
          private final TheStaticThingFunctionality func; 
          Client() { this(new TheStaticThingImpl()); } 
          Client(TheStaticThingFunctionality func) { this.func = func; } 
      

      이 코드는 당신이 할 수 있습니다

    이제는 예외적으로 비행 할 때 컨트롤을 사용할 수 있습니다. 그리고 더 중요한 것은 : 당신은 이미 Apachece Commons가 제공 한 구현에서 자신을 분리시키는 첫 발걸음을 내디뎠습니다. 이제 StaticThingImpl을 필요에 따라 다른 것으로 교환 할 수 있습니다.

  • +0

    더 자세히 설명해 주시겠습니까? 내가 뭘 하려는지 하나의 파일에 잔뜩 파일을 병합하는 것입니다. 이 작업을 위해 Apache Commons FileUtils 라이브러리를 사용하고 있으며 사용하는 읽기/쓰기 작업으로 인해 모두 IOException이 발생할 수 있습니다. 예외가 발생하면 모든 것을 원래 상태로 되돌려 놓아야합니다. 이는 반 완성 된 병합 파일을 지우는 것을 의미합니다. 나는 예외를 다루는 것 외에 많은 선택의 여지가없는 것처럼 보입니다. –

    +0

    내 업데이트보기! – GhostCat