Robolectric 给我 java.lang.IllegalArgumentException:需要 INTERNET 许可
Roboelectric is giving me a java.lang.IllegalArgumentException: INTERNET permission is required
我正在对现有应用程序进行单元测试改造。当我运行这个简单的单元测试
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.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.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=12=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
at org.robolectric.RobolectricTestRunner.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.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.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=12=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
at org.robolectric.RobolectricTestRunner.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.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",
}
但不想
添加
<uses-permission android:name="android.permission.INTERNET" />
在您的 AndroidManifest.xml
中的应用程序标记之外
显然,当 运行 单元测试使用 robolectric 时,将不会启用权限。
检查段库,它检查互联网权限如下:
/** Returns true if the application has the given permission. */
public static boolean hasPermission(Context context, String permission) {
return context.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED;
}
但是如前所述,em 运行 测试您的应用程序将没有互联网权限(但是您将能够进行互联网通话)您可以通过向影子应用程序授予互联网权限来解决这个问题,并且然后在段库中使用此上下文。
将此方法添加到您的 TestApp
protected Context instance() {
ShadowApplication shadowApp = Shadows.shadowOf(this);
shadowApp.grantPermissions("android.permission.INTERNET");
return shadowApp.getApplicationContext();
}
并将您的代码更改为此
Analytics.with(instance()).identify("userId", null, null);
希望对你有帮助。
我几乎尝试了所有提到的所有方法,但没有任何效果,所以我想出了这个解决方案。问题基本上是,Roboelectric 在 运行 测试时调用应用程序 class 的 onCreate()
,我在其中实例化了段 SDK,因此它抛出了 IllegalArgumentException
和我所有的测试都失败了。
为了解决这个问题,我从应用程序 class 的 onCreate()
中删除了初始化调用,现在我正在对段 SDK 进行延迟初始化。
现在我在需要发送第一个事件时初始化 SDK,一旦初始化,Analytics
对象的单例实例将在整个应用程序的生命周期中使用。
这样我就不必触及您现有的任何测试用例,而且 Segment 也能正常工作。
我通过创建测试应用程序并用它覆盖运行时应用程序来解决。在此测试应用程序中,使用影子应用程序授予权限。这样您就不会接触任何实际应用程序来执行测试。
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);
}
}
下面是单元测试class
@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, application = ShadowTestApp.class )
public class TestThis {
@Test
public void blah(){
assertTrue(true);
}
}
我 运行 遇到同样的问题并按如下方式修复它 -
将需要 INTERNET 权限的 SDK [在我的例子中是 Segment] 初始化为一个单独的函数,如下所示 -
@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);
}
创建一个包含上述方法的 class 的影子并将此方法重写为 return 空。
或
您也可以使用 Mockito 来 return 每当调用 initializeSegmentSdk()
方法时什么都不做
我正在对现有应用程序进行单元测试改造。当我运行这个简单的单元测试
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.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.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=12=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
at org.robolectric.RobolectricTestRunner.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.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.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=12=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
at org.robolectric.RobolectricTestRunner.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.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",
}
但不想
添加
<uses-permission android:name="android.permission.INTERNET" />
在您的 AndroidManifest.xml
中的应用程序标记之外显然,当 运行 单元测试使用 robolectric 时,将不会启用权限。 检查段库,它检查互联网权限如下:
/** Returns true if the application has the given permission. */
public static boolean hasPermission(Context context, String permission) {
return context.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED;
}
但是如前所述,em 运行 测试您的应用程序将没有互联网权限(但是您将能够进行互联网通话)您可以通过向影子应用程序授予互联网权限来解决这个问题,并且然后在段库中使用此上下文。
将此方法添加到您的 TestApp
protected Context instance() {
ShadowApplication shadowApp = Shadows.shadowOf(this);
shadowApp.grantPermissions("android.permission.INTERNET");
return shadowApp.getApplicationContext();
}
并将您的代码更改为此
Analytics.with(instance()).identify("userId", null, null);
希望对你有帮助。
我几乎尝试了所有提到的所有方法,但没有任何效果,所以我想出了这个解决方案。问题基本上是,Roboelectric 在 运行 测试时调用应用程序 class 的 onCreate()
,我在其中实例化了段 SDK,因此它抛出了 IllegalArgumentException
和我所有的测试都失败了。
为了解决这个问题,我从应用程序 class 的 onCreate()
中删除了初始化调用,现在我正在对段 SDK 进行延迟初始化。
现在我在需要发送第一个事件时初始化 SDK,一旦初始化,Analytics
对象的单例实例将在整个应用程序的生命周期中使用。
这样我就不必触及您现有的任何测试用例,而且 Segment 也能正常工作。
我通过创建测试应用程序并用它覆盖运行时应用程序来解决。在此测试应用程序中,使用影子应用程序授予权限。这样您就不会接触任何实际应用程序来执行测试。
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);
}
}
下面是单元测试class
@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, application = ShadowTestApp.class )
public class TestThis {
@Test
public void blah(){
assertTrue(true);
}
}
我 运行 遇到同样的问题并按如下方式修复它 -
将需要 INTERNET 权限的 SDK [在我的例子中是 Segment] 初始化为一个单独的函数,如下所示 -
@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);
}
创建一个包含上述方法的 class 的影子并将此方法重写为 return 空。
或
您也可以使用 Mockito 来 return 每当调用 initializeSegmentSdk()
方法时什么都不做