2015-05-05 4 views
5

Ich bin auf Android Studio 1.2, Robolectric 3.0-rc2.einige Robolectric Tests scheitern, wenn alle zusammen laufen, aber einzeln übergeben

Ich habe zwei Testklassen, eine MotdTest mit einer Testmethode, die für POJO Json Serialisierung & Deserialisierung testet. Die andere heißt UserInfoTest, die 4 Testmethoden enthält, die auf Benutzerinformationen testen, die ich in SharedPreferences einstelle. Wenn ich UserInfoTest einzeln betreibe, sind alle 4 Testmethoden immer bestanden. Wenn ich jedoch alle Tests durchführe, ist der Test in MotdTest erfolgreich, aber zwei Methoden von UserInfoTest schlagen immer fehl. Ich bin von der Kommandozeile ausgeführt wird jetzt durch ./gradlew test

Aufruf

Weiß jemand, warum einige meiner Tests fehlschlagen, wenn ich alle Tests laufen? In meinem UserInfoTest habe ich richtigerweise eine @After annotierte Methode, wo ich Aufräumen durch den Aufruf von clear(). Commit() auf dem SharedPreferences.Editor.

UserInfoTest:

testOnSignIn() bei assertThat(6, equalTo(prefs.getAll().size())); schlägt fehl, da die Größe der prefs ist 0.

Und testIsSignedIn() bei assertThat(UserInfo.isSignedIn(), is(false));

@RunWith(MyRoboRunner.class) 
@Config(constants = BuildConfig.class) 
public class UserInfoTest { 

    private String mExpectedId; 

    private String mExpectedName; 

    private String mExpectedEmail; 

    private String mExpectedToken; 

    private String mExpectedKey; 

    @Before 
    public void setUp() throws Exception { 
     ShadowLog.stream = System.out; 

     mExpectedId = "someiD"; 
     mExpectedName = "johnny boy"; 
     mExpectedEmail = "[email protected]"; 
     mExpectedToken = "Session Token"; 
     mExpectedKey = "Session Key"; 
    } 

    @After 
    public void tearDown() { 
     SharedPreferences prefs = RuntimeEnvironment.application.getSharedPreferences(
       UserInfo.PREFERENCES, Context.MODE_PRIVATE); 
     prefs.edit().clear().commit(); 
     mExpectedId = null; 
     mExpectedName = null; 
     mExpectedEmail = null; 
     mExpectedToken = null; 
     mExpectedKey = null; 
    } 

    @Test 
    public void testOnSignIn() {   
     SharedPreferences prefs = RuntimeEnvironment.application.getSharedPreferences(
       UserInfo.PREFERENCES, Context.MODE_PRIVATE); 

     UserInfo.onSignIn(mExpectedId, mExpectedName, mExpectedEmail, mExpectedKey, mExpectedToken); 
     assertThat(mExpectedKey, equalTo(UserInfo.getSessionKey())); 

     assertThat(mExpectedToken, equalTo(UserInfo.getSessionToken())); 
     assertThat(mExpectedId, equalTo(UserInfo.getUserId())); 
     assertThat(mExpectedEmail, equalTo(UserInfo.getUserEmail())); 
     assertThat(mExpectedName, equalTo(UserInfo.getUserName())); 

     assertThat(6, equalTo(prefs.getAll().size())); 
    } 

    @Test 
    public void testOnSignOut() { 
     UserInfo.onSignIn(mExpectedId, mExpectedName, mExpectedEmail, mExpectedKey, mExpectedToken); 
     // Set Over21 to make sure we unset this value on Signout 
     UserInfo.setIsOver21(true); 

     UserInfo.onSignOut(); 
     SharedPreferences prefs = RuntimeEnvironment.application.getSharedPreferences(
       UserInfo.PREFERENCES, Context.MODE_PRIVATE); 
     assertThat(UserInfo.getSessionKey(), nullValue()); 
     assertThat(UserInfo.getSessionToken(), nullValue()); 
     assertThat(UserInfo.isOver21Set(), is(false)); 
     assertThat(prefs.getAll().size(), equalTo(0)); 
    } 

    @Test 
    public void testIsSignedIn() { 
     assertThat(UserInfo.isSignedIn(), is(false)); 

     UserInfo.onSignIn(mExpectedId, mExpectedName, mExpectedEmail, mExpectedKey, mExpectedToken); 
     assertThat(UserInfo.isSignedIn(), is(true)); 

     UserInfo.onSignOut(); 
     assertThat(UserInfo.isSignedIn(), is(false)); 
    } 

    @Test 
    public void testIsOver21Set() { 
     assertThat(UserInfo.isOver21Set(), is(false)); 
     UserInfo.setIsOver21(false); 
     assertThat(UserInfo.isOver21Set(), is(true)); 
    } 
} 

Userinfo versagt:

App ist eine Application Unterklasse ein d App.getInstance() ist ein Singleton.

private static final SharedPreferences PREFS = App.getInstance() 
     .getSharedPreferences(PREFERENCES, Context.MODE_PRIVATE); 

public static void onSignIn(String userId, String fullName, String email, String sessionKey, 
     String sessionToken) { 
    SharedPreferences.Editor editor = PREFS.edit(); 
    editor.putString(PROPERTY_USER_ID, userId); 
    editor.putString(PROPERTY_USER_NAME, fullName); 
    editor.putString(PROPERTY_USER_EMAIL, email); 
    editor.putString(PROPERTY_SESSION_KEY, sessionKey); 
    editor.putString(PROPERTY_SESSION_TOKEN, sessionToken); 
    editor.putStringSet(PROPERTY_PENDING_SCANS, new HashSet<String>()); 

    editor.commit(); 
} 
public static boolean isSignedIn() { 
    return getSessionToken() != null; 
} 

MyRoboRunner: Eine modifizierte Version von this, weil ich auf dem Mac bin, und auch, weil ich API 22 in meinem Projekt Targeting, aber robolectric unterstützt noch nicht zu, dass, so dass ich betreibe meine Tests gegen API 21.

public class MyRoboRunner extends RobolectricGradleTestRunner { 

    public MyRoboRunner(Class<?> klass) throws InitializationError { 
     super(klass); 
    } 

    protected AndroidManifest getAppManifest(Config config) { 
     AndroidManifest appManifest = super.getAppManifest(config); 
     String moduleRoot = getModuleRootPath(config); 

     //can use this line instead dynamic path resolution when AS bug is fix, or use @Config 
     //FsFile androidManifestFile = appManifest.getAndroidManifestFile(); 
     FsFile androidManifestFile = FileFsFile.from(moduleRoot, 
       appManifest.getAndroidManifestFile().getPath() 
         .replace("bundles", "manifests/full")); 
     FsFile resDirectory = FileFsFile.from(moduleRoot, appManifest.getResDirectory().getPath()); 
     FsFile assetsDirectory = FileFsFile 
       .from(moduleRoot, appManifest.getAssetsDirectory().getPath()); 
     return new AndroidManifest(androidManifestFile, resDirectory, assetsDirectory) { 
      @Override 
      public int getTargetSdkVersion() { 
       //lollipop bc it's highest that robolectric 3.0 supports 
       return Build.VERSION_CODES.LOLLIPOP; 
      } 

      @Override 
      public int getMinSdkVersion() { 
       return Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1; 
      } 
     }; 
    } 

    private String getModuleRootPath(Config config) { 
     String moduleRoot = config.constants().getResource("").toString().replace("file:", ""); 
     return moduleRoot.substring(0, moduleRoot.indexOf("/build")); 
    } 
} 
+0

Welche Art von Fehler sehen Sie? Können Sie den Code für Tests freigeben? –

+0

@EugenMartynov Ich habe einen Teil des Codes, den ich für die Tests verwende, eingefügt. – waynesford

Antwort

0

die robolectric gradle plugin und Festlegen dieser Eigenschaft verwendet, hat alle meine Tests vorbei:

robolectric { 
    // Specify max number of processes (default is 1) 
    maxParallelForks = 2 
} 

Aber ich weiß immer noch nicht, warum dies mein t beeinflussen würde wenn sie einzeln oder alle zusammen laufen. Außerdem scheint es, dass das robolectric gradle Plugin nicht mehr notwendig ist, da ich Android Studio 1.2 verwende, aber ich konnte nicht herausfinden, wie ich es ohne es funktioniere und die Eigenschaft maxParallelForks manuell setzen.

+1

Dies ist eine Problemumgehung, aber keine richtige Lösung –

1

Sie behalten statische Referenzen auf SharedPreferences in der PREFS. Ich denke, dass Ihre Tests behoben werden, sobald Sie es in Ihrer tearDown Methode zurücksetzen oder statische Referenzen überhaupt entfernen. Wenn Sie die statische Referenz entfernen, wird die SharedPreferences Datei von Robolectric selbst gelöscht - Sie müssen sie nicht erneut in tearDown löschen.

Ein weiterer Punkt zu erwähnen - ich verwende auch Mac und ich habe kein Problem mit RobolectricGradleTestRunnner. Manchmal muss ich clean ausführen, bevor ich die Tests durchführe, aber sonst nichts.

Und eine andere Sache, die Sie erwähnten robobolectric-gradle-plugin. Sie brauchen es nicht mit Android Studio v1.1 + und Android Gradle Plugin V1.1 +

Verwandte Themen