来自WebSettings的Android robolectric InstantiationException

时间:2012-10-23 19:12:14

标签: android testing intellij-idea robolectric

我在运行一些测试用例时遇到问题,在将api升级到4.1之后中断了(不确定它是否相关,但错误似乎并不是这样)

java.lang.RuntimeException: java.lang.InstantiationException
at com.xtremelabs.robolectric.bytecode.RobolectricInternals.newInstanceOf(RobolectricInternals.java:32)
at com.xtremelabs.robolectric.Robolectric.newInstanceOf(Robolectric.java:130)
at com.xtremelabs.robolectric.shadows.ShadowWebView.<init>(ShadowWebView.java:21)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at java.lang.Class.newInstance0(Class.java:355)
at java.lang.Class.newInstance(Class.java:308)
at com.xtremelabs.robolectric.bytecode.ShadowWrangler.shadowFor(ShadowWrangler.java:163)
at com.xtremelabs.robolectric.bytecode.ShadowWrangler$InvocationPlan.prepare(ShadowWrangler.java:311)
at com.xtremelabs.robolectric.bytecode.ShadowWrangler.methodInvoked(ShadowWrangler.java:81)
at com.xtremelabs.robolectric.bytecode.RobolectricInternals.methodInvoked(RobolectricInternals.java:111)
at android.view.View.<init>(View.java)
at android.view.ViewGroup.<init>(ViewGroup.java)
at android.widget.AbsoluteLayout.<init>(AbsoluteLayout.java)
at android.webkit.WebView.<init>(WebView.java)
在给定的ShadowWebView类中

, 有一行

private WebSettings webSettings = Robolectric.newInstanceOf(WebSettings.class);

上述行导致

  Robolectric.java

然后导致RobolectricInternals.java并执行以下方法

   public static <T> T newInstanceOf(Class<T> clazz)

该方法具有以下源代码:

public static <T> T newInstanceOf(Class<T> clazz) {
    try {
        Constructor<T> defaultConstructor = clazz.getDeclaredConstructor();
        defaultConstructor.setAccessible(true);
        return defaultConstructor.newInstance();
    } catch (InstantiationException e) {
        throw new RuntimeException(e);
    } catch (IllegalAccessException e) {
        throw new RuntimeException(e);
    } catch (NoSuchMethodException e) {
        throw new RuntimeException(e);
    } catch (InvocationTargetException e) {
        throw new RuntimeException(e);
    }
}

抛出的异常(你在上面的错误日志中看到)是因为这行

    defaultConstructor.newInstance();

我不确定是什么导致了这个以及如何解决这个问题 我所做的只是观察得到的是来自android的WebSettings.java曾经是一个非抽象类,但现在它是一个抽象类,我认为这是罪魁祸首,但是当我切换到等级12的旧api时,(对于哪个websettings.java没有声明为abstract),我仍然有相同的错误

1 个答案:

答案 0 :(得分:0)

你是正确的,Android的WebSettings成为API 16中的抽象类。

在API 16,Robolectric无法再通过以下方式创建WebSettings实例:

private WebSettings webSettings = Robolectric.newInstanceOf(WebSettings.class);

因为WebSettings是抽象的,即使通过反射也无法实例化。

因为WebSettings变得抽象,所以Robolectric必须以某种方式提供WebSettings的具体实例。所以我创建了android.webkit.TestWebSettings类,并让Robolectric在ShadowWebView#getSettings中返回了一个实例。

至于您的具体问题 - 您已切换到API 12但仍无法实例化WebSettings。即使您将项目更改为较低的API级别,也可能是这种情况,因为Robolectric本身仍然是针对android-16.jar构建的。如果您更改Robolectric本身以针对android-12.jar进行构建,您将获得一个WebSettings实例 - 但没有阴影实现,因为ShadowWebSettings已从当前版本的Robolectric中删除。

您问题的最简单的解决方法可能是将项目更新为API 16,然后直接在测试用例中实例化TestWebSettings对象。所以而不是:

private WebSettings webSettings = Robolectric.newInstanceOf(WebSettings.class);
你会写:

private WebSettings webSettings = new TestWebSettings();

您可以在android.webkit包中找到属于Robolectric源的TestWebSettings类:

import android.webkit.TestWebSettings;