2014-06-20 6 views
8

Robolectric을 사용하여 Parse.com에서 푸시 알림을 테스트하려고합니다. Application 클래스에서 초기화가 수행되어야하므로 테스트해야합니다. 지금까지이 응용 프로그램은 에뮬레이터에서 잘 작동하지만 Robolectric로는 테스트 할 수 없습니다. 응용 프로그램 클래스의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) 

답변

7

당신은 어떤 클래스에 구문 분석 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); 
    } 
} 
내가 입력하는 동안 어떤 실수를하지 않는 경우이 작업을해야

@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); 
} 

} 

:

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(); 
} 

이 테스트 응용 프로그램 및 테스트를 수정 :

앱을 수정합니다.

물론 이것은 대략적인 아이디어입니다. 테스트에서 익명의 클래스를 작성하는 대신 모의 라이브러리 (mock library)를 사용하는 것이 더 좋습니다 (My favorite은 Mockito 임). 또한 의존성 반전과 주입 (IoC)에 대해 읽어보십시오. 그리고 (http://robolectric.blogspot.nl/2013/04/the-test-lifecycle-in-20.html를 참조하시기 바랍니다)

2
public class TestParseApplication extends Application 

이 테스트 세트 또는 테스트 스위트가 아닌 테스트중인 실제 클래스해야이 응용 프로그램 테스트에서 Robolectric 테스트 응용 프로그램을 분리하는 훨씬 더 지속됩니다.

각 테스트에 대해 Application 클래스를 인스턴스화해야합니다. 실제로 Robolectric은 매니페스트에 Application 클래스를 적절하게 선언하고 robolectric API에서 현재 응용 프로그램 인스턴스 (향상된 테스트 기능 포함)를 얻을 수있는 경우 getShadowApplication()을 사용합니다.

관련 문제