2011-09-28 9 views
8

Estoy tratando de escribir pruebas de unidad para mi aplicación de Android y quiero burlarme de mi clase de servicio. Quiero probar algunos comportamientos de error en el servicio, como errores de conexión o archivos no encontrados.¿Es posible burlarse de los servicios de android bajo pruebas unitarias?

Para simplificar mi pregunta, iniciado un nuevo proyecto Android y crearon una actividad y una clase de servicio:

MyAndroidProjectActivity.java

package br.org.venturus.android; 

import android.app.Activity; 
import android.content.ComponentName; 
import android.content.Context; 
import android.content.Intent; 
import android.content.ServiceConnection; 
import android.os.Bundle; 
import android.os.IBinder; 
import android.view.View; 
import android.widget.TextView; 
import br.org.venturus.android.service.MyService; 

public class MyAndroidProjectActivity extends Activity { 
    private MyService service; 
    private ServiceConnection mConnection = new ServiceConnection() { 

     public void onServiceConnected(ComponentName className, IBinder binder) { 
      service = ((MyService.MyBinder) binder).getService(); 

     } 

     public void onServiceDisconnected(ComponentName className) { 
      service = null; 
     } 
    }; 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     { 
      Intent service = new Intent(this, MyService.class); 
      startService(service); 

      bindService(service, mConnection, Context.BIND_AUTO_CREATE); 
     } 

    } 

    @Override 
    protected void onDestroy() { 
     super.onDestroy(); 
     // stop MyService 
     { 
      Intent svc = new Intent(this, MyService.class); 
      stopService(svc); 
     } 
    } 

    public void doChange(View view) { 
     TextView tv = (TextView) findViewById(R.id.tvHello); 

     tv.setText(service.getNewString()); 
    } 
} 

MyService.java

package br.org.venturus.android.service; 

import br.org.venturus.android.R; 
import android.app.Service; 
import android.content.Intent; 
import android.os.Binder; 
import android.os.IBinder; 

public class MyService extends Service { 

    private IBinder binder; 

    public MyService() { 
     this.binder = new MyBinder(); 
    } 
    @Override 
    public IBinder onBind(Intent intent) { 
     return binder; 
    } 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 

    } 

    public class MyBinder extends Binder { 
     public MyService getService() { 
      return MyService.this; 
     } 
    } 

    public String getNewString() { 
     return getString(R.string.change); 
    } 

} 

Y creé un nuevo Android Test Project con esta unidad clas s:

MyAndroidProjectActivityTest.java

package br.org.venturus.android.test; 

import android.test.ActivityInstrumentationTestCase2; 
import android.test.UiThreadTest; 
import android.widget.Button; 
import android.widget.TextView; 
import br.org.venturus.android.MyAndroidProjectActivity; 
import br.org.venturus.android.R; 

public class MyAndroidProjectActivityTest extends 
     ActivityInstrumentationTestCase2<MyAndroidProjectActivity> { 

    private MyAndroidProjectActivity mActivity; 
    private TextView tvHello; 
    private Button btChange; 

    public MyAndroidProjectActivityTest() { 
     super("br.org.venturus.android", MyAndroidProjectActivity.class); 
    } 

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

     // Get the activity and components 
     { 
      mActivity = this.getActivity(); 
      tvHello = (TextView) mActivity 
        .findViewById(br.org.venturus.android.R.id.tvHello); 
      btChange = (Button) mActivity 
        .findViewById(br.org.venturus.android.R.id.btChange); 
     } 

    } 

    public void testPreconditions() { 
     assertNotNull(tvHello); 
     assertNotNull(btChange); 
    } 

    @UiThreadTest 
    public void testChangeButton() { 
     assertEquals(tvHello.getText(), getActivity().getString(R.string.hello)); 
     btChange.performClick(); 
     assertEquals(tvHello.getText(), getActivity() 
       .getString(R.string.change)); 
    } 
} 

Cuando ejecuto las pruebas unitarias, las condiciones previas y las pruebas botón de cambio están bien. Lo que quiero hacer, por ejemplo, es crear un MyServiceMock y anular MyService.getNewString para devolver otro valor y simular este objeto en la prueba.

Algo como esto:

MyServiceMock.java

package br.org.venturus.android.test.service; 

import br.org.venturus.android.service.MyService; 

public class MyServiceMock extends MyService { 
    @Override 
    public String getNewString() {  
     return "This is the new value!"; 
    } 
} 

¿Es posible?

Respuesta

3

Sí, es posible y creo que el ejemplo de la MyServiceMock.java anterior es también una alternativa.

Existen algunos frameworks burlones que puedes usar para esto.

Tengo alguna experiencia con Mockito.

Puede simplemente burlarse de la clase MyService y especificar que cuando se llame al método getNewString, devuelva una cadena "¡Este es el nuevo valor!".

MyService myServiceMock = Mockito.mock(MyService.class); 

Mockito.doReturn("This is the new value!").when(myServiceMock).getNewString(); 

También puede utilizar el Mockito.doThrow() método para producir una excepción cuando un método simulacro se llama:

Mockito.doThrow(new RuntimeException()).when(mockedList).clear(); 

//following throws RuntimeException: 
mockedList.clear(); 
+1

expectativas ajuste es la parte fácil, pero ¿cómo reemplazar la servicio declarado en el manifiesto iniciado por el marco y todo el ciclo de vida vinculante con el objeto simulado que ha creado: 'myServiceMock'? – TWiStErRob

Cuestiones relacionadas