Robolectric给了我一个java.lang.IllegalArgumentException:需要INTERNET权限

问题描述 投票:4回答:5

我正在将UnitTests改造为现有的应用程序。当我运行这个简单的单元测试时

import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.annotation.Config;
import static junit.framework.Assert.assertTrue;

@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, packageName = "com.blah.blah" )
public class TestThis {

@Test
public void blah(){
    assertTrue(true);
   }
}

我收到这个错误

java.lang.IllegalArgumentException: INTERNET permission is required.
at com.segment.analytics.Analytics$Builder.<init>(Analytics.java:585)
at com.segment.analytics.Analytics.with(Analytics.java:115)
at org.robolectric.internal.ParallelUniverse.setUpApplicationState(ParallelUniverse.java:140)
at org.robolectric.RobolectricTestRunner.setUpApplicationState(RobolectricTestRunner.java:433)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:240)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:188)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:152)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
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 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

java.lang.RuntimeException: java.lang.IllegalArgumentException: INTERNET permission is required.
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:244)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:188)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:152)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
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)
Caused by: java.lang.IllegalArgumentException: INTERNET permission is required.
at com.segment.analytics.Analytics$Builder.<init>(Analytics.java:585)
at com.segment.analytics.Analytics.with(Analytics.java:115)
at org.robolectric.internal.ParallelUniverse.setUpApplicationState(ParallelUniverse.java:140)
at org.robolectric.RobolectricTestRunner.setUpApplicationState(RobolectricTestRunner.java:433)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:240)

我的第一个假设是,robolectric没有得到清单,但它似乎在那里。我有什么基本的东西吗?

对不起,我写这篇文章的时候很匆忙,应该补充一些细节

我在清单中确实有这个

<uses-permission android:name="android.permission.INTERNET" />

我在阅读本页Robolectric junit test - missing internet permission后尝试明确设置清单

另一个更新,问题是onCreate()中触发的http调用

public class TestApp extends Application {

@Override
public final void onCreate() {
    super.onCreate();
    singleton = this;
    if (!BuildConfig.DEBUG) { Fabric.with(this, new Crashlytics()); }
    loadData();
    // The next line makes the http call 
    Analytics.with(getApplicationContext()).identify("userId", null, null);
    RequestQueues.initInstance(singleton);
}
}   

有什么想法吗?我可以补充一下

if (notTest)
{
  com.segment.analytics.Analytics.with(getApplicationContext()).identify("userId",     
} 

但不愿意

java android robolectric
5个回答
8
投票

显然,当使用robolectric运行单元测试时,不会启用权限。检查Segment lib,它会检查Internet权限,如下所示:

 /** Returns true if the application has the given permission. */
  public static boolean hasPermission(Context context, String permission) {
    return context.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED;
  }

但正如所说,运行测试你的应用程序将没有互联网权限(但你可以进行互联网调用)你可以通过给予影子应用程序的互联网权限然后在段lib中使用此上下文来解决这个问题。

将此方法添加到TestApp

protected Context instance() {
        ShadowApplication shadowApp = Shadows.shadowOf(this);
        shadowApp.grantPermissions("android.permission.INTERNET");

        return shadowApp.getApplicationContext();
    }

并将您的代码更改为此

Analytics.with(instance()).identify("userId", null, null);

希望它对你有所帮助。


1
投票

我通过创建测试应用程序并使用它覆盖运行时应用程序来解决。在此测试应用程序中,使用shadow app授予权限。这样您就不会触及任何实际应用程序来执行测试。

public class ShadowTestApp extends TestApp {
    @Override
    public final void onCreate() {
        ShadowApplication shadowApp = Shadows.shadowOf(this);
        shadowApp.grantPermissions("android.permission.INTERNET");

     Analytics.with(shadowApp.getApplicationContext()).identify("userId", null, null);
    }
}

以下是单元测试类

@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, application = ShadowTestApp.class )
public class TestThis {

    @Test
    public void blah(){
        assertTrue(true);
    }
}

0
投票

我尝试了几乎所有提到的所有内容,没有任何对我有用,所以我想出了这个解决方案。问题基本上是,Roboelectric在运行测试时调用应用程序类的onCreate()并在那里实例化段SDK,因此它抛出了IllegalArgumentException并且我的所有测试都失败了。

为了解决这个问题,我从应用程序类的onCreate()中删除了初始化调用,现在我正在进行段SDK的延迟初始化。

现在我在需要发送第一个事件时初始化SDK,一旦初始化,在整个应用程序的生命周期中使用Analytics对象的单例实例。

这样我就不必触及任何现有的测试用例,Segment也可以正常工作。


0
投票

我遇到了同样的问题并修复如下 -

初始化SDK [在我的案例中]段,需要INTERNET权限作为单独的函数,如下所示 -

@VisibleForTesting()
public void initializeSegmentSdk() {
    // Create an analytics client with the given context and Segment write key.
    Analytics analytics = new Analytics.Builder(this, "xyz")
    // Enable this to record certain application events automatically!
    .trackApplicationLifecycleEvents()
    // Enable this to record screen views automatically!
    .recordScreenViews()
    .build();

    // Set the initialized instance as a globally accessible instance.
    Analytics.setSingletonInstance(analytics);
}

创建一个包含上述方法的类的阴影,并重写此方法以返回空。

要么

每当调用initializeSegmentSdk()方法时,您也可以使用Mockito返回任何内容


-3
投票

<uses-permission android:name="android.permission.INTERNET" /> 

在AndroidManifest.xml中的应用程序标记之外

© www.soinside.com 2019 - 2024. All rights reserved.