Reiniciar la aplicación en la prueba de Android

Estoy haciendo una biblioteca que procesará la información de acuerdo con la configuración predeterminada del usuario y la guardará en SharedPreferences, que puede ser modificada por el desarrollador en su aplicación antes de inicializar mi biblioteca.

El SDK sólo debe inicializarse una vez por instancia de aplicación, otherwised activará un RuntimeError. Así que en el lado de la aplicación en la clase de aplicación debe ser algo como esto:

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

La implementación abstracta sdk:

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

El problema viene cuando quiero probar varios escenarios para llamar a este método (que sólo se puede llamar una vez por instancia de aplicación).

Así que he creado una prueba de Android que extiende el ApplicationTest

ApplicationTest:

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

Muestra de prueba de Android:

 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 } } 

Intenté terminar y crear la aplicación de nuevo, pero sin éxito. Mi pregunta es que es posible reiniciar la aplicación de una prueba de Android? ¿Estoy haciendo algo mal aquí?

Creo que el problema con el que realmente estás luchando es el problema de InstrumentationTestRunner : ¿Cómo evitar que ActivityUnitTestCase llame a Application.onCreate? (Y, al parecer, no hay solución obvia para ello)

Es decir TestRunner va a llamar onCreate() durante su inicialización de todos modos, así que una vez que llame a createApplication() , su Sdk ya está inicializado.

Respecto a la pregunta en sí misma, creo que la única opción es repensar la arquitectura de la clase Sdk (o agregar alguna función "reset", etc.)

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

Clase Sdk

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

Pruebas:

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

¡NÓTESE BIEN! Puedes hacerlo un poco menos paiful, si aplicas AndroidManifest especial para androidTest. Entonces, no tendrá problemas con el problema de TestRunner, cuando llama a onCreate () por sí mismo antes de iniciar las pruebas.

Espero que ayude

  • Mockito: ¿Cómo uso getString con mockito?
  • Obtener un contexto para su uso en AndroidTestCase cuando la clase bajo prueba no es una actividad
  • Prueba de una clase Fragment en aislamiento usando Mockito
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.