android - test - ¿Unidad de prueba de un receptor de difusión?
robolectric (3)
Desde que se hizo esta pregunta, los marcos burlones han evolucionado bastante. Con mockito ahora puedes burlarte no solo de las interfaces sino también de las clases. Así que sugeriría resolver este problema simulando un contexto y usando ArgumentCapture:
import static org.mockito.Mockito.*;
public class OutgoingCallReceiverTest extends AndroidTestCase {
private OutgoingCallReceiver mReceiver;
private Context mContext;
@Override
protected void setUp() throws Exception {
super.setUp();
//To make mockito work
System.setProperty("dexmaker.dexcache",
mContext.getCacheDir().toString());
mReceiver = new OutgoingCallReceiver();
mContext = mock(Context.class);
}
public void testStartActivity() {
Intent intent = new Intent(Intent.ACTION_NEW_OUTGOING_CALL);
intent.putExtra(Intent.EXTRA_PHONE_NUMBER, "01234567890");
mReceiver.onReceive(mContext, intent);
assertNull(mReceiver.getResultData());
ArgumentCaptor<Intent> argument = ArgumentCaptor.forClass(Intent.class);
verify(mContext, times(1)).startActivity(argument.capture());
Intent receivedIntent = argument.getValue();
assertNull(receivedIntent.getAction());
assertEquals("01234567890", receivedIntent.getStringExtra("phoneNum"));
assertTrue((receivedIntent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0);
}
}
Aquí hay un BroadcastReceiver de mi proyecto, que estoy buscando para la prueba de unidad. Cuando el usuario hace una llamada telefónica, toma el número de teléfono y establece la intención de comenzar una nueva actividad, pasando el número de teléfono.
public class OutgoingCallReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context xiContext, Intent xiIntent)
{
if (xiIntent.getAction().equalsIgnoreCase(Intent.ACTION_NEW_OUTGOING_CALL))
{
String phoneNum = xiIntent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Intent intent = new Intent(xiContext, MyActivity.class);
intent.putExtra("phoneNum", phoneNum);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
xiContext.startActivity(intent);
setResultData(null);
}
}
}
Hasta ahora, mi prueba de unidad se ve así:
public class OutgoingCallReceiverTest extends AndroidTestCase
{
private OutgoingCallReceiver mReceiver;
@Override
protected void setUp() throws Exception
{
super.setUp();
mReceiver = new OutgoingCallReceiver();
}
public void testStartActivity()
{
Intent intent = new Intent(Intent.ACTION_NEW_OUTGOING_CALL);
intent.putExtra(Intent.EXTRA_PHONE_NUMBER, "01234567890");
mReceiver.onReceive(getContext(), intent);
}
}
Esto se ejecuta a través del código, pero quiero que mi prueba pueda verificar que se envió la intención y verificar el número de teléfono. ¿Cómo hago esto?
¿También puedo probar que la llamada telefónica se cancele (debido a la línea setResultData (null))?
Mate,
Parece que necesitas un Contexto ... y luego intercambias tus métodos para aceptar interfaces en lugar de clases concretas: public void onReceive(IContext c, IIntent i)
, solo para los fines de prueba. Pero las clases de Contexto e Intención no son tuyas, son ... son de Android ... así que no puedes "simplemente" hacer que implementen tus interfaces, así que tendrías que "envolverlas" para poder Exponga su interfaz, que es RATHER una gran cantidad de código para no mucho beneficio. Muy asqueroso
Así que empecé a preguntarme si alguien había pasado por todo esto antes, y hizo los patios duros por nosotros ... y tada: http://developer.android.com/reference/android/test/mock/package-summary.html
Aclamaciones. Keith.
corlettk me señaló el objeto MockContext en Android, que funciona. He hecho una subclase de ella, TestContext, que se parece a esto:
public class TestContext extends MockContext
{
private List<Intent> mReceivedIntents = new ArrayList<Intent>();
@Override
public String getPackageName()
{
return "com.mypackage.test";
}
@Override
public void startActivity(Intent xiIntent)
{
mReceivedIntents.add(xiIntent);
}
public List<Intent> getReceivedIntents()
{
return mReceivedIntents;
}
}
Y mi caso de prueba ahora se ve así:
public class OutgoingCallReceiverTest extends AndroidTestCase
{
private OutgoingCallReceiver mReceiver;
private TestContext mContext;
@Override
protected void setUp() throws Exception
{
super.setUp();
mReceiver = new OutgoingCallReceiver();
mContext = new TestContext();
}
public void testStartActivity()
{
Intent intent = new Intent(Intent.ACTION_NEW_OUTGOING_CALL);
intent.putExtra(Intent.EXTRA_PHONE_NUMBER, "01234567890");
mReceiver.onReceive(mContext, intent);
assertEquals(1, mContext.getReceivedIntents().size());
assertNull(mReceiver.getResultData());
Intent receivedIntent = mContext.getReceivedIntents().get(0);
assertNull(receivedIntent.getAction());
assertEquals("01234567890", receivedIntent.getStringExtra("phoneNum"));
assertTrue((receivedIntent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0);
}
}