2012-07-06 16 views
5

que tienen esta clase de prueba para probar un servicio remoto:servicio de Android no lanzada por prueba unitaria

public class CoreServiceBasicTest extends ServiceTestCase<CoreService> implements ServiceConnection { 

    /** Tag for logging */ 
    private final static String TAG = CoreServiceBasicTest.class.getName(); 

    /** Receive incoming messages */ 
    private final Messenger inMessenger = new Messenger(new IncomingHandler()); 

    /** Communicate with the service */ 
    private Messenger outMessenger = null; 

    /** Handler of incoming messages from service */ 
    private static class IncomingHandler extends Handler { 

     @Override 
     public void handleMessage(Message msg) { 
      Log.d(TAG, "Incoming message"); 
     } 
    } 

    /** Constructor for service test */ 
    public CoreServiceBasicTest() { 
     super(CoreService.class); 
    } 

    /** Start the service */ 
    @Override 
    public void setUp() { 

     // Mandatory 
     try { 
      super.setUp(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

     // Start the service 
     Intent service = new Intent(); 
     service.setClass(this.getContext(), CoreService.class); 
     startService(service); 
     Log.d(TAG, "Service started"); 
    } 

    public void onServiceConnected(ComponentName className, IBinder service) { 
     outMessenger = new Messenger(service); 
     Log.d(TAG, "Service attached"); 
    } 

    public void onServiceDisconnected(ComponentName className) { 
     // TODO Auto-generated method stub 

    } 

    @SmallTest 
    public void testBindService() { 
     // Bind to the service 
     Intent service = new Intent(); 
     service.setClass(getContext(), CoreService.class); 
     boolean isBound = getContext().bindService(service, this, Context.BIND_AUTO_CREATE); 
     assertTrue(isBound); 
    } 
} 

El problema es que StartService (servicio) en el método setup() no se inicia el servicio correctamente. Esto es lo que muestra la AVD:

enter image description here

Como se puede ver, se puso en marcha el proceso, pero el servicio no es. Luego, el testBindService(), assertTrue(isBound) falla.

Esto no sucede si pongo en marcha el servicio de una actividad:

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    // Start the Core service 
    Intent service = new Intent(); 
    service.setClass(this, CoreService.class); 

    if (startService(service) == null) { 
     Toast.makeText(this, "Error starting service!", Toast.LENGTH_LONG).show(); 
     Log.e(TAG, "Error starting service"); 
    } else { 
     Toast.makeText(this, "Service started sucessfully", Toast.LENGTH_LONG).show(); 
    } 

    // Die 
    finish(); 
} 

Aquí el servicio se inicia correctamente, como se muestra a continuación.

enter image description here

¿Cómo puedo iniciar y se unen a un servicio remoto que usa Messenger para comunicarse con las actividades de un proyecto de prueba de Android?

+0

Haga primero estos controles para que podamos asegurarnos de que es un problema central y no algo sintáctico primero Asegúrese su manifiesto tiene este '' y está anidado entre la etiqueta de la aplicación como ' ' También asegúrese de que todas las dependencias del proyecto estén correlacionadas correctamente. Compruebe también si su coreservice.java está en el mismo paquete o un paquete diferente como actividad: asegúrese de tener los nombres de los paquetes en el manifiesto. – Slartibartfast

+0

Como dije: * "Esto no ocurre si lanzo el servicio desde una Actividad" *, así que obviamente el Manifiesto es correcto. Además, como puede ver, no aparece el error "No se encontró el servicio", pero el proceso se inicia pero no hay servicio. Esto es lo que encuentro extraño. – m0skit0

Respuesta

11

El objetivo de Android Test Project (test.apk) es instrumentar el Application Project (app.apk) y probar los componentes de Android (Activity, Service y etc.) asociados con Application Project, en otro palabra, actividad de la unidad de pruebas de servicio y que se crea y manipula el interior app.apk.

Usted no debe escribir su aplicación MessengerService parcialmente (Messenger, IncomingHandler y etc) por segunda vez dentro de la aplicación ServiceTestCase bajo el proyecto de prueba. Sólo necesita ser escrita una vez en el archivo CoreService.java de su proyecto de aplicación para la aplicación MessengerService.

ServiceConnection se utiliza para la comunicación entre Activity y Service, ya que utilizamos ServiceTestCase aquí (significa servicio de prueba unitaria, la comunicación con otros componentes está fuera del alcance por lo tanto no se considera), no necesitamos una ServiceConnection implementación. Lo único que hace es ServiceConnection inicializar un objeto sólido mensajero para que pudiéramos utilizar más adelante, una vez que el servicio se creó correctamente:

public void onServiceConnected(ComponentName className, IBinder service) { 
    // This is what we want, we will call this manually in our TestCase, after calling 
    // ServiceTestCase.bindService() and return the IBinder, check out code sample below. 
    mService = new Messenger(service); 
} 

También tenga en cuenta que no es necesario llamar a ServiceTestCase.startService() en este caso, como ServiceTestCase.bindService() iniciará el servicio correctamente (si aún no se ha iniciado) y devolverá un objeto IBinder que necesitamos usar para inicializar el objeto Messenger más tarde.

Diga si su impelementation IncomingHandler.handleMessage() en CoreService.java aspecto:

... ... 

switch (msg.what) { 
    case MSG_SAY_HELLO: 
    msgReceived = true; 
    break; 

... ... 

Para probar las funciones enviar mensaje en ServiceTestCase:

... ... 

IBinder messengerBinder = null; 

@Override 
public void setUp() throws Exception { 
    super.setUp(); 
    // Bind the service and get a IBinder: 
    messengerBinder = bindService(new Intent(this.getContext(), CoreService.class)); 
    //log service starting 
    Log.d(TAG, "Service started and bound"); 
} 

public void testSendMessage() { 
    // Use IBinder create your Messenger, exactly what we did in ServiceConnection callback method: 
    Messenger messenger = new Messenger(messengerBinder); 
    Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0); 
    messenger.send(msg); 
    // Do some assert stuff here 
    ... ... 
} 

... ... 

Si usted quiere poner a prueba la comunicación entre Actividad y servicio, entonces ServiceTestCase no es adecuado en este caso. Considere el uso de ActivityInstrumentationTestCase2 pruebe la actividad real (que se une a su CoreService, que le da la capacidad de probar indirectamente sus funciones de servicio.

+0

Sí, eso es exactamente lo que quería hacer: probar el envío del mensaje al servicio, no la aplicación <-> comunicación de servicio. ¡Gracias! – m0skit0

+0

@ m0skit0, me alegra oír que ayuda :) – yorkw

7

sola observación de la documentation for ServiceTestCase se dice que el marco de pruebas retrasos de iniciar el servicio hasta que uno de sus métodos de prueba llama ServiceTestCase.startService() o ServiceTestCase.bindService().

En cuanto a su código que llama a su método de ServiceTestCase.startService() en setUp(), no en un método de prueba. Esto no inicia el servicio todavía. Se está a la espera de uno de sus métodos de prueba para llamar ServiceTestCase.startService() o ServiceTestCase.bindService().

Su método de prueba testBindService() no está llamando al ServiceTestCase.bindService(), sino que está llamando al Context.bindService() y está fallando. El marco de pruebas todavía está esperando, así que por eso no se inicia el servicio.

Eche un vistazo a Soporte de ciclo de vida discusión en los documentos de desarrollador vinculados.

+0

El problema es que no puedo llamar a 'ServiceTestCase.bindService()', eso es inútil para mí, ya que no toma 'ServiceConnection'. – m0skit0

+1

El marco de prueba trata con todas las cosas de conexión. Administra el ServiceConnection. Cuando llama a 'ServiceTestCase.bindService()' devuelve un IBinder, que es lo que habría utilizado ServiceConnection para todos modos. En cualquier caso, si no puede usar este marco de prueba para su prueba porque no proporciona las capacidades o la interfaz que necesita, entonces solo tendrá que escribir su propio arnés de prueba sin utilizar este marco. –

Cuestiones relacionadas