Android: Unidad de prueba de un servicio
Actualmente estoy intentando escribir una aplicación de Android usando TDD. Me han dado la tarea de escribir un servicio que será muy importante en la aplicación.
Como por esta razón estoy tratando de escribir una prueba adecuada para el servicio. Las directrices de Android indican lo siguiente:
- Iniciar servicio desde la notificación
- Gestión de devoluciones de llamada del servicio remoto
- MVC en Android: ¿Aplicación o servicio para actualizaciones asíncronas?
- Cómo utilizar NotificationCompat.Builder y startForeground?
- Subida de imágenes de Android: ¿Utilizar actividad o servicio?
El tema Qué probar enumera las consideraciones generales para probar componentes de Android. Aquí hay algunas pautas específicas para probar un servicio:
Asegúrese de que onCreate () se llama en respuesta a Context.startService () o Context.bindService (). Del mismo modo, debe asegurarse de que onDestroy () se llama en respuesta a Context.stopService (), Context.unbindService (), stopSelf () o stopSelfResult (). Pruebe que su Servicio gestiona correctamente varias llamadas desde Context.startService (). Sólo la primera llamada activa Service.onCreate (), pero todas las llamadas activan una llamada a Service.onStartCommand ().
Además, recuerde que las llamadas de startService () no anidan, por lo que una sola llamada a Context.stopService () o Service.stopSelf () (pero no stopSelf (int)) detendrá el servicio. Debe probar que su Servicio se detiene en el punto correcto.
Pruebe cualquier lógica de negocio que implemente su Servicio. La lógica de negocio incluye la comprobación de valores no válidos, cálculos financieros y aritméticos, etc.
Fuente: Pruebas de servicio | Desarrolladores de Android
Todavía tengo que ver una prueba adecuada para estos métodos de ciclo de vida, múltiples llamadas a Context.startService (), etc Estoy tratando de averiguar esto, pero estoy actualmente en una pérdida.
Estoy intentando probar el servicio con la clase de ServiceTestCase:
import java.util.List; import CoreManagerService; import org.junit.After; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Before; import org.junit.Test; import android.app.ActivityManager; import android.app.ActivityManager.RunningServiceInfo; import android.content.Context; import android.content.Intent; import android.test.ServiceTestCase; import android.test.suitebuilder.annotation.SmallTest; import android.util.Log; /** * * This test should be executed on an actual device as recommended in the testing fundamentals. * http://developer.android.com/tools/testing/testing_android.html#WhatToTest * * The following page describes tests that should be written for a service. * http://developer.android.com/tools/testing/service_testing.html * TODO: Write tests that check the proper execution of the service's life cycle. * */ public class CoreManagerTest extends ServiceTestCase<CoreManagerService> { /** Tag for logging */ private final static String TAG = CoreManagerTest.class.getName(); public CoreManagerTest () { super(CoreManagerService.class); } public CoreManagerTest(Class<CoreManagerService> serviceClass) { super(serviceClass); // If not provided, then the ServiceTestCase will create it's own mock // Context. // setContext(); // The same goes for Application. // setApplication(); Log.d(TAG, "Start of the Service test."); } @SmallTest public void testPreConditions() { } @BeforeClass public static void setUpBeforeClass() throws Exception { } @AfterClass public static void tearDownAfterClass() throws Exception { } @Before public void setUp() throws Exception { super.setUp(); } @After public void tearDown() throws Exception { super.tearDown(); } @Test public void testStartingService() { getSystemContext().startService(new Intent(getSystemContext(), CoreManagerService.class)); isServiceRunning(); } private void isServiceRunning() { final ActivityManager activityManager = (ActivityManager)this.getSystemContext() .getSystemService(Context.ACTIVITY_SERVICE); final List<RunningServiceInfo> services = activityManager .getRunningServices(Integer.MAX_VALUE); boolean serviceFound = false; for (RunningServiceInfo runningServiceInfo : services) { if (runningServiceInfo.service.getClassName().equals( CoreManagerService.class.toString())) { serviceFound = true; } } assertTrue(serviceFound); } }
¿Me estoy acercando a esto incorrectamente? ¿Debo usar una prueba de actividad para probar la vinculación del servicio contra?
- Android - Ejecutar en segundo plano - Service vs. standard java class
- Uso de Alarmmanager para iniciar un servicio en un momento específico
- Android - vistas de servicio
- Actualizar Android ListView en Widget
- ¿Es posible ejecutar mi servicio por tiempo indefinido?
- Cómo llamar al método en servicio de otra actividad
- ¿Puede Android ServiceTestCase <MyService> enviar mensajes a mi servicio?
- Servicio de Android - URL de ping
Hay un ejemplo con JUnit 4 :
Servicio:
/** * {@link Service} that generates random numbers. * <p> * A seed for the random number generator can be set via the {@link Intent} passed to * {@link #onBind(Intent)}. */ public class LocalService extends Service { // Used as a key for the Intent. public static final String SEED_KEY = "SEED_KEY"; // Binder given to clients private final IBinder mBinder = new LocalBinder(); // Random number generator private Random mGenerator = new Random(); private long mSeed; @Override public IBinder onBind(Intent intent) { // If the Intent comes with a seed for the number generator, apply it. if (intent.hasExtra(SEED_KEY)) { mSeed = intent.getLongExtra(SEED_KEY, 0); mGenerator.setSeed(mSeed); } return mBinder; } public class LocalBinder extends Binder { public LocalService getService() { // Return this instance of LocalService so clients can call public methods. return LocalService.this; } } /** * Returns a random integer in [0, 100). */ public int getRandomInt() { return mGenerator.nextInt(100); } }
Prueba:
public class LocalServiceTest { @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); @Test public void testWithBoundService() throws TimeoutException { // Create the service Intent. Intent serviceIntent = new Intent(InstrumentationRegistry.getTargetContext(), LocalService.class); // Data can be passed to the service via the Intent. serviceIntent.putExtra(LocalService.SEED_KEY, 42L); // Bind the service and grab a reference to the binder. IBinder binder = mServiceRule.bindService(serviceIntent); // Get the reference to the service, or you can call public methods on the binder directly. LocalService service = ((LocalService.LocalBinder) binder).getService(); // Verify that the service is working correctly. assertThat(service.getRandomInt(), is(any(Integer.class))); } }