unitarias test studio run pruebas mock dependency android junit

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