¿Cómo puedo probar una Intención lanzada / enviada desde una Actividad?
¿Cómo puedo crear un caso de prueba de Android JUnit que pruebe el contenido de un intento generado dentro de una actividad?
Tengo una actividad que contiene una ventana de EditText, y cuando el usuario ha terminado de introducir los datos requeridos, la actividad lanza una intención a un IntentService que registra los datos y continúa con el proceso de la aplicación. Aquí es la clase que quiero probar, el OnEditorActionListener / PasscodeEditorListener se crea como una clase separada:
- Cómo JUnit prueba IntentService
- qué prueba de unidad, en aplicaciones Android
- Fuentes de la biblioteca de soporte de pruebas en Android Studio
- Compartir código entre pruebas de instrumentación de Android y pruebas de unidad en Android Studio
- AssertionFailedError en ApplicationTestCase.createApplication () en versiones más recientes de Android cuando se utiliza MockContext
public class PasscodeActivity extends BaseActivity { EditText m_textEntry = null; PasscodeEditorListener m_passcodeEditorListener = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.passcode_activity); m_passcodeEditorListener = new PasscodeEditorListener(); m_textEntry = (EditText) findViewById(R.id.passcode_activity_edit_text); m_textEntry.setTag(this); m_textEntry.setOnEditorActionListener(m_passcodeEditorListener); } @Override protected void onPause() { super.onPause(); /* * If we're covered for any reason during the passcode entry, * exit the activity AND the application... */ Intent finishApp = new Intent(this, CoreService.class); finishApp.setAction(AppConstants.INTENT_ACTION_ACTIVITY_REQUESTS_SERVICE_STOP); startService(finishApp); finish(); } } class PasscodeEditorListener implements OnEditorActionListener{ @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { PasscodeActivity activity = (PasscodeActivity) v.getTag(); boolean imeSaysGo = ((actionId & EditorInfo.IME_ACTION_DONE)!=0)?true:false; boolean keycodeSaysGo = ((null != event) && (KeyEvent.ACTION_DOWN == event.getAction()) && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER))?true:false; if (imeSaysGo || keycodeSaysGo){ CharSequence seq = v.getText(); Intent guidEntry = new Intent(activity, CoreService.class); guidEntry.setAction(AppConstants.INTENT_ACTION_PASSCODE_INPUT); guidEntry.putExtra(AppConstants.EXTRA_KEY_GUID, seq.toString()); activity.startService(guidEntry); return true; } return false; } }
¿Cómo puedo interceptar los dos posibles intentos de salida generados por la actividad y verificar su contenido?
Gracias
- ChooserActivity no se encuentra con las pruebas Robotium mientras ChooserActivity se muestra en Nexus 5
- ¿Cómo continuar una prueba de instrumentación Android después de una excepción?
- Algo falta en mi proyecto de prueba de Android?
- Espresso - haga clic en el texto en la vista de lista
- Prácticas recomendadas para la prueba de unidades de Android?
- Permisos de solo prueba de Android con gradle
- AndroidJUnit4 y pruebas parametrizadas
- Robolectric: probar un ListView con el patrón ViewHolder causa NullPointerException
Pensé en cómo utilizar ContextWrapper con la ayuda de otro sitio web.
Utilice ContextWrapper y anule todas las funciones de intención. Generalizando para todas mis pruebas de actividad, extendí la clase ActivityUnitTestCase e implementé la solución como un shim. Disfrutar:
import android.app.Activity; import android.app.Instrumentation; import android.content.ComponentName; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.test.ActivityUnitTestCase; public class IntentCatchingActivityUnitTestCase<T extends Activity> extends ActivityUnitTestCase<T> { protected Activity m_activity; protected Instrumentation m_inst; protected Intent[] m_caughtIntents; protected IntentCatchingContext m_contextWrapper; protected class IntentCatchingContext extends ContextWrapper { public IntentCatchingContext(Context base) { super(base); } @Override public ComponentName startService(Intent service) { m_caughtIntents = new Intent[] { service }; return service.getComponent(); } @Override public void startActivities(Intent[] intents) { m_caughtIntents = intents; super.startActivities(intents); } @Override public void startActivity(Intent intent) { m_caughtIntents = new Intent[] { intent }; super.startActivity(intent); } @Override public boolean stopService(Intent intent) { m_caughtIntents = new Intent[] { intent }; return super.stopService(intent); } } // --// public IntentCatchingActivityUnitTestCase(Class<T> activityClass) { super(activityClass); } protected void setUp() throws Exception { super.setUp(); m_contextWrapper = new IntentCatchingContext(getInstrumentation().getTargetContext()); setActivityContext(m_contextWrapper); startActivity(new Intent(), null, null); m_inst = getInstrumentation(); m_activity = getActivity(); } protected void tearDown() throws Exception { super.tearDown(); } }
Alternativamente, usted podría volver a factorizar su código para hacer "limpio" unidad de prueba (me refiero a una prueba de unidad que tiene todo burlado excepto la clase bajo prueba). En realidad, tengo una situación yo mismo, donde recibo una java.lang.RuntimeException: Stub!
Porque el código que quiero probar la unidad crea nuevos Intentes que contienen simulacros que he inyectado.
Considero la creación de mi propia fábrica para intentos. Entonces podría inyectar una fábrica despreciada a mi clase bajo prueba:
public class MyClassToBeTested { public MyClassToBeTested(IntentFactory intentFactory) { //assign intentFactory to field } .... public void myMethodToTestUsingIntents() { Intent i = intentFactory.create(); i.setAction(AppConstants.INTENT_ACTION_PASSCODE_INPUT); //when doing unit test, inject a mocked version of the //IntentFactory and do the necessary verification afterwards. .... } }
Mi situación no es la misma que la tuya, pero creo que podrías aplicar un patrón de fábrica para resolverlo también. Yo prefiero escribir código para soportar verdaderas pruebas de unidad, pero debo admitir que su solución es bastante inteligente.
- Ventaja de almacenamiento de datos sin esquema en el almacenamiento de datos con el esquema
- Android modo de pantalla completa (ICS), el primer toque muestra la barra de navegación