Pruebas de unidades de Android que requieren contexto

Estoy escribiendo mi primer backend de la base de datos de Android y estoy luchando para probar la creación de mi base de datos.

Actualmente el problema que estoy encontrando es la obtención de un objeto de contexto válido para pasar a mi implementación de SQLiteOpenHelper. ¿Existe una manera de obtener un objeto Context en una clase que extienda TestCase? La solución que he pensado es para instanciar una actividad en el método de instalación de mi TestCase y luego asignar el contexto de esa actividad a una variable de campo que mis métodos de prueba pueden acceder … pero parece que debería haber una manera más fácil.

¡Gracias por tu aportación!

Macy

Puede intentar cambiar a AndroidTestCase . De mirar los documentos, parece que debería ser capaz de proporcionarle un Contexto válido para pasar a SQLiteOpenHelper.

Editar: Tenga en cuenta que probablemente tendrá que tener sus pruebas de configuración en un "Proyecto de prueba de Android" en Eclipse, ya que las pruebas se intentará ejecutar en el emulador (o dispositivo real).

Si está ejecutando las pruebas con AndroidJUnit4 , puede utilizar los métodos de InstrumentationRegistry para obtener un contexto:

InstrumentationRegistry.getTargetContext() : proporciona la aplicación Context de la aplicación de destino;

InstrumentationRegistry.getContext() – proporciona el Context del paquete de esta Instrumentación;

El uso del AndroidTestCase:getContext() sólo proporciona un stub Context en mi experiencia. Para mis pruebas, estoy utilizando una actividad vacía en mi aplicación principal y obtener el Context través de eso. También estoy extendiendo la clase de conjuntos de pruebas con la clase ActivityInstrumentationTestCase2 . Parece funcionar para mi.

 public class DatabaseTest extends ActivityInstrumentationTestCase2<EmptyActivity> EmptyActivity activity; Context mContext = null; ... @Before public void setUp() { activity = getActivity(); mContext = activity; } ... //tests to follow } 

¿Qué hacen los demás?

Debe utilizar ApplicationTestCase o ServiceTestCase.

Extender AndroidTestCase y llamar a AndroidTestCase: getContext () ha funcionado bien para mí para obtener el contexto y utilizarlo con una base de datos SQLite.

El único inconveniente es que la base de datos que crea y / o utiliza será la misma que la utilizada por la aplicación de producción, por lo que es probable que desee utilizar un nombre de archivo diferente para ambos

p.ej.

  public static final String NOTES_DB = "notestore.db"; public static final String DEBUG_NOTES_DB = "DEBUG_notestore.db"; 

Puede derivar de MockContext y devolver por ejemplo un MockResources en getResources() , un ContentResolver válido en getContentResolver() , etc. Eso permite, con cierto dolor, algunas pruebas unitarias .

La alternativa es ejecutar por ejemplo Robolectric que simula todo un sistema operativo Android. Ésos serían para las pruebas del sistema : Es mucho más lento funcionar.

Primero cree la clase de prueba bajo (androidTest).

Ahora use el código siguiente:

 public class YourDBTest extends InstrumentationTestCase { private DBContracts.DatabaseHelper db; private RenamingDelegatingContext context; @Override public void setUp() throws Exception { super.setUp(); context = new RenamingDelegatingContext(getInstrumentation().getTargetContext(), "test_"); db = new DBContracts.DatabaseHelper(context); } @Override public void tearDown() throws Exception { db.close(); super.tearDown(); } @Test public void test1() throws Exception { // here is your context context = context; }} 

Solución alternativa es evitar el uso de ApplicationTestCase o AndroidTestCase o cualquier otra clase que dependen de Context . El punto es que no hay necesidad de probar el marco de SQLite o ORM para que pueda crear la interfaz con los métodos básicos de CRUD :

 public interface UsersManager{ User createUser(String userId); User getUser(String userId); boolean updateUser(User user); boolean deleteUser(User user); } 

E implementar dos versiones: una para pruebas y otra para producción en tiempo de ejecución. La versión para pruebas podría implementarse fácilmente con HashMap :

 public class TestUsersManager implements UsersManager{ private HashMap<String, User> users = new HashMap(); public User createUser(String userId){ User result = new User(userId); users.put(userId, user); return result; } //... other methods } 

Funciona rápido (sin IO disco en caso de SQLite ) y no tiene dependencias externas. Por cierto esto también es un nivel adicional de abstracción: para el código de producción que podría cambiar fácilmente entre los marcos de ORM por ejemplo.

  • Robolectric Unit Test falla con las actualizaciones de Android Studio 2.3
  • Cómo determinar la unidad de píxeles (px, dp, etc) de una vista en Java?
  • Cómo ejecutar todas las pruebas (unitarias e instrumentadas) con un solo clic en Android Studio
  • Ejecutar pruebas de unidad en Guardar con Android Studio
  • Granja de dispositivos AWS con Espresso y JUnit4
  • Acceso al contexto de la aplicación desde TestSuite en Setup () antes de llamar a getActivity ()
  • Intento de mockito de simular cualquier clase genera ExceptionInInitializerError
  • Prueba de unidad en Android Studio: error "no escarnecido"
  • Pruebas Robolectric que se ejecutan en Android Studio pero no en la línea de comandos
  • ¿Cómo puedo crear pruebas en Android Studio?
  • Anotación @UiThreadTest produce "java.lang.Exception: No se pueden ejecutar métodos"
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.