2015-12-18 14 views
6

Sto creando una libreria che elaborerà le informazioni in base alle impostazioni predefinite dell'utente e la salverà su SharedPreferences, che può essere modificata dallo sviluppatore sulla loro applicazione prima di inizializzare la mia libreria.Riavvio dell'applicazione su Android test

L'SDK deve essere inizializzato solo una volta per ogni istanza dell'applicazione, altrimenti verrà attivato un RuntimeError. Quindi, sul lato applicazione su classe di applicazione dovrebbe essere qualcosa di simile:

public class SampleApplication extends Application { 
    @Override 
    public void onCreate() { 
     super.onCreate(); 

     //Here I can do something that will change the default configs 

     //Here I initialize the SDK singleton method 
     Sdk.initialize(); 
    } 
} 

SDK astratto realizzazione:

public class Sdk { 

    private static SampleApplication sInstance; 

    private void Sdk(){ 
    } 

    public static SampleApplication getInstance() throws RuntimeException { 
     if (sInstance == null) { 
      throw new RuntimeException(); 
     } 
     return sInstance; 
    } 

    public static void initialize() { 
     if (sInstance == null) { 
      sInstance = new Sdk(); 
      //save some information according to what is on the default configurations 
     } else { 
      throw new RuntimeException("Method was already initialized"); 
     } 
    } 
} 

Il problema nasce quando voglio testare diversi scenari per chiamare questo metodo (che può solo essere chiamato una volta per istanza dell'applicazione).

Così ho creato un test di Android, che estende l'ApplicationTest

ApplicationTest:

public class ApplicationTest extends ApplicationTestCase<SampleApplication> { 
     public ApplicationTest() { 
      super(SampleApplication.class); 
     } 
    } 

Android campione da analizzare:

public class SampleTest extends ApplicationTest { 

    @Override 
    protected void setUp() throws Exception { 
// Here I restart the user preferences although I need to restart the application 
//  terminateApplication(); 
//  createApplication(); 
     super.setUp(); 
    } 

    @Override 
    protected void tearDown() throws Exception { 
     super.tearDown(); 
    } 

    public void testDefaultSettings() { 
     // Here is where I want to restart application input 
     // some values on the user preferences settings in order 
     // to test the output on sharedpreferences by the initialized method 
    } 
} 

ho cercato di interrompere e creare di nuovo l'applicazione, ma senza successo . La mia domanda è che è possibile riavviare l'applicazione di un test di Android? Sto facendo qualcosa di sbagliato qui?

risposta

1

credo, il problema è davvero alle prese con è un InstrumentationTestRunner 's problema: How to prevent ActivityUnitTestCase from calling Application.onCreate? (e, a quanto pare, non c'è alcuna correzione ovvio per esso)

Vale a dire TestRunner chiamerà onCreate() durante l'inizializzazione, quindi, una volta chiamato createApplication(), il tuo Sdk è già inizializzato.

Per quanto riguarda la domanda stessa - io credo, l'unica opzione è quella di ripensare l'architettura della classe Sdk (o l'aggiunta di una funzione "reset", ecc)

public class TestApplication extends Application { 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     // Sdk.terminate(); - If you specify TestApplication as an 
     //     application class in AndroidManifest, 
     //     you'll have to uncomment this(due to issue with test runner) 
     Sdk.initialize(); 
    } 

    @Override 
    public void onTerminate() { 
     super.onTerminate(); 
     Sdk.terminate(); 
    } 
} 

Sdk classe

public class Sdk { 

    private static Sdk sInstance; 
    private void Sdk(){ 
    } 

    public static Sdk getInstance() throws RuntimeException { 
     if (sInstance == null) { 
      throw new RuntimeException(); 
     } 
     return sInstance; 
    } 

    public static void terminate() { 
     sInstance = null; 
    } 

    public static void initialize() { 
     if (sInstance == null) { 
      sInstance = new Sdk(); 
      //save some information according to what is on the default configurations 
     } else { 
      throw new RuntimeException("Method was already initialized"); 
     } 
    } 
} 

Test:

public class MyApplicationTest extends ApplicationTestCase<TestApplication> { 

    public MyApplicationTest() { 
     super(TestApplication.class); 
    } 

    public void testMultiplicationTests() { 
     createApplication(); 

     int answer = 42; 
     assertEquals(42, answer); 

     terminateApplication(); 
    } 


    public void testDefaultSettings() { 
     createApplication(); 

     assertNotNull(Sdk.getInstance()); 

     terminateApplication(); 
    } 
} 

NB! Puoi renderlo un po 'meno paessoso, se applichi AndroidManifest speciale per AndroidTest. Quindi, non avrai problemi con il problema di TestRunner, quando invocherà onCreate() da solo prima dell'avvio dei test.

Spero che sia d'aiuto

+0

Ciao, grazie per la spiegazione su come funziona correttamente il test runner. Ho solo un dubbio sulla tua congestione, "1 test per classe" vuoi dire eseguire una classe di test per installazione? – iGoDa

+0

@ iGoDa, intendevo che una volta che hai più classi ognuna delle quali estende ApplicationTestCase, ognuna di esse creerebbe una nuova istanza dell'app => non ci sarebbero sovrapposizioni tra di esse. Ma di nuovo, è un po 'brutto e ti limita ad avere un solo test per classe ApplocationTesCase. –

+0

AndroidTest accetta più applicationTestCases per pacchetto AndroidTest?Dopo tutto AndroidTest è un'applicazione giusta? Devo modificare qualsiasi configurazione per quel lavoro? – iGoDa

Problemi correlati