ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy,android PowerMock与JUnit有什么关系?

9

我正在使用PowerMock和Mockito来测试一个静态函数,如下所示。直到今天它都可以很好地工作,但现在它会抛出下面提到的异常。

// this test case need to mock static methods so it uses PowerMock
@RunWith(PowerMockRunner.class)
// this static methods to be mocked are on Environment so that must be 'prepared'
@PrepareForTest({Environment.class, Build.class, Build.VERSION.class})
public class FileUtilityUnitTest {
    //This uses the JUnit TemporaryFolder Rule to create
    // (and discard on completion) a directory for the assertions.
    @Rule
    TemporaryFolder storageDirectory = new TemporaryFolder();
    File nonExistentDirectory;
    File existentDirectory;

    @Before
    public void setup(){
        PowerMockito.mockStatic(Environment.class);
        PowerMockito.mockStatic(Build.VERSION.class);
        nonExistentDirectory = Mockito.mock(File.class);
        //so the exists method tends to be false
        when(nonExistentDirectory.exists()).thenReturn(false);
        existentDirectory = storageDirectory.getRoot();
    }

    @Test
    public void test_is_external_storage_writable(){
        when(Environment.getExternalStorageState()).thenReturn(Environment.MEDIA_MOUNTED);
        assertTrue("External storage mounted ", Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED);
    }
}

以下是堆栈跟踪。

    Internal Error occured.
java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy
    at sun.reflect.annotation.AnnotationParser.parseClassArray(AnnotationParser.java:724)
    at sun.reflect.annotation.AnnotationParser.parseArray(AnnotationParser.java:531)
    at sun.reflect.annotation.AnnotationParser.parseMemberValue(AnnotationParser.java:355)
    at sun.reflect.annotation.AnnotationParser.parseAnnotation2(AnnotationParser.java:286)
    at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:120)
    at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:72)
    at java.lang.Class.createAnnotationData(Class.java:3521)
    at java.lang.Class.annotationData(Class.java:3510)
    at java.lang.Class.getAnnotation(Class.java:3415)
    at com.intellij.junit4.JUnit4TestRunnerUtil.buildRequest(JUnit4TestRunnerUtil.java:150)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:93)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

有谁能解释一下这个问题呢?我已经搜索了一番,但没有找到好的参考资料。 提前感谢。


如果你使用Maven来运行测试,例如...你是否会得到任何异常?看起来像是一个错误的想法。 - Maciej Kowalski
我不确定如何使用Maven运行测试。您能否发布一些我可以尝试的命令@MaciejKowalski。 - Vansi
3个回答

2
今天我遇到了同样的问题。我不确定发生了什么,但是通过将compileSdkVersionbuildToolsVersiontargetSdkVersion更新为与support-annotations版本相匹配,问题已经解决了。
现在,build.gradle看起来像这样:
android {
  compileSdkVersion 27
  buildToolsVersion "27.0.2"

  defaultConfig {
    ...
    targetSdkVersion 27
  }
}

dependencies {
  compile 'com.android.support:support-annotations:27.0.2'
  androidTestCompile 'com.android.support:support-annotations:27.0.2'
}

我没有找到关于它的太多评论,所以我希望能帮助一些人。


1
我有一个需要注意的观察结果。我在某处看到说这是由于生成的android.jar导致的构建问题。
我不知道原因,但我尝试将compileVersion从26更改为25(26和25没有区别。我只是更改了另一个我安装的版本),然后重新构建项目。
同样的测试用例再次开始工作而没有失败。

1
一种可能导致Junit测试抛出TypeNotPresentExceptionProxy异常的原因是某些依赖项使用compileOnly而不是implementation。
由于编译SDK版本的原因很重要,可能是因为SDK删除了您正在模拟的那些类。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接