android - 如何使用 Robolectric 测试 Application 类?

标签 android parse-platform robolectric

我正在尝试使用 Robolectric 测试 Parse.com 的推送通知。由于必须在 Application 类中完成初始化,因此我需要对其进行测试。到目前为止,该应用程序在模拟器上运行良好,但我无法使用 Robolectric 对其进行测试。

我的应用类的onCreate:

public void onCreate() {
            super.onCreate();

            // Add your initialization code here
            Parse.initialize(this, APP_KEY,
                            CLIENT_ID);

            // Specify an Activity to handle all pushes by default.
            PushService.setDefaultPushCallback(this, MainActivity.class);

            // Save the current Installation to Parse.
            //This is null on test
            android_id = Secure.getString(getApplicationContext()
                            .getContentResolver(), Secure.ANDROID_ID);

            System.out.println("android id >>" + android_id);

            ParseInstallation installation = ParseInstallation
                            .getCurrentInstallation();
            installation.put("UniqueId", android_id);
            installation.saveInBackground();

            ParseUser.enableAutomaticUser();
            ParseACL defaultACL = new ParseACL();

            // If you would like all objects to be private by default, remove this
            // line.
            defaultACL.setPublicReadAccess(true);
            Parse.setLogLevel(Parse.LOG_LEVEL_VERBOSE);
            ParseACL.setDefaultACL(defaultACL, true);
    }

测试

@RunWith(RobolectricTestRunner.class)
public class TestParseApplication extends Application {
private ParseApplication parseApplication;

@Before
public void setup() {

    parseApplication = new ParseApplication();
    parseApplication.android_id = "123";

    Robolectric.application = parseApplication;
}

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

}

堆栈跟踪

WARNING: no system properties value for ro.build.date.utc
android id >>null

java.lang.IllegalArgumentException: Must subscribe to channel with a valid icon identifier.
        at com.parse.PushService.setDefaultPushCallback(PushService.java:298)
        at com.parse.PushService.setDefaultPushCallback(PushService.java:277)
        at com.parse.starter.ParseApplication.onCreate(ParseApplication.java:30)
        at org.robolectric.internal.ParallelUniverse.setUpApplicationState(ParallelUniverse.java:164)
        at org.robolectric.RobolectricTestRunner.setUpApplicationState(RobolectricTestRunner.java:430)
        at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:236)
        at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
        at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:177)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
        at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
        at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

最佳答案

您应该将 Parse API 包装到某个类中并模拟它:

public class ParseAPI {
   public void init(Context context, String key, String id) {
        // Add your initialization code here
        Parse.initialize(context, key,
                        id);
   }

   public void initPush(Context context, Class pushCallbackClass) {
        // Specify an Activity to handle all pushes by default.
        PushService.setDefaultPushCallback(context, puchCallbackClass);
   }
}

修改您的应用:

public void onCreate() {
    super.onCreate();

    ParseAPI api = getParseAPI();

    api.init(this, APP_KEY, CLIENT_ID)
    api.initPush(this, MainActivity.class);
}

protected ParseAPI getParseAPI() {
    return new ParseAPI();
}

修改您的测试应用和测试:

@RunWith(RobolectricTestRunner.class)
public class TestParseApplication extends ParseApplication {
private ParseApplication parseApplication;

@Before
public void setup() {

    parseApplication = new TestParseApplication();
    parseApplication.android_id = "123";

    Robolectric.application = parseApplication;
}

protected ParseAPI getParseAPI() {
    return new ParseAPI() {
               public void init(Context context, String key, String id) {
               }

               public void initPush(Context context, Class pushCallbackClass) {
               }
    };
}

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

}

如果我在输入时没有出现任何错误,这应该可以工作。

当然这是粗略的想法。最好使用一些模拟库而不是在测试中编写匿名类(我最喜欢的是 Mockito)。另请阅读依赖倒置和注入(inject) (IoC)。最后,最好将 Robolectric 测试应用程序与应用程序测试分开(请阅读 http://robolectric.blogspot.nl/2013/04/the-test-lifecycle-in-20.html)

关于android - 如何使用 Robolectric 测试 Application 类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24319770/

相关文章:

javascript - 如何计算 Parse 平台上的 BeforeSave CloudCode 中的总用户数

android - 使用 Dagger 和 Robolectric 注入(inject)服务

java - 使用 Robolectric 测试启动 Activity 的代码

java - 无法应用CompoundButton 中的setOnCheckedChangeListener

java - 邻区信息不准确

android - 返回上一个 Activity

java - Robolectric 运行测试时无法找到资源 ID

java - 如何加速 Android 多行 Edittext 中的平滑滚动?

java - 我从解析服务器获取损坏的文件 url

ios - 如何向用户好友发送推送通知