Dado que el método getApplicationContext
se encuentra dentro de la clase que está ampliando, se convierte en algo problemático. Hay un par de problemas a tener en cuenta:
- Usted realmente no puede burlarse de una clase que está bajo prueba, que es uno de los muchos inconvenientes con herencia de objetos (es decir, la subclasificación).
- El otro problema es que
ApplicationContext
es singleton, lo que lo hace más difícil de probar ya que no se puede simular fácilmente un estado global que está programado para ser irremplazable.
Lo que puede hacer en esta situación es a preferir object composition over inheritance. Por lo tanto, para que tu Activity
se pueda probar, debes dividir la lógica un poco. Digamos que su Activity
se llama MyActivity
. Tiene que ser compuesto de un componente lógico (o clase), llámelo MyActivityLogic
. Aquí es una figura simple clase diagrama:

para resolver el problema Singleton, dejamos que la lógica sea "inyecta" con un contexto de aplicación, por lo que se puede probar con una maqueta. Entonces solo tenemos que probar que el objeto MyActivity
haya puesto el contexto de aplicación correcto en MyActivityLogic
. Cómo resolvemos básicamente ambos problemas es a través de another layer of abstraction (parafraseado de Butler Lampson). La nueva capa que agregamos en este caso es la lógica de actividad movida fuera del objeto de actividad.
Por el bien de tu ejemplo las clases tienen que mirar clase-de la siguiente manera:
public final class MyActivityLogic {
private MyApp mMyApp;
public MyActivityLogic(MyApp pMyApp) {
mMyApp = pMyApp;
}
public MyApp getMyApp() {
return mMyApp;
}
public void onClick(View pView) {
getMyApp().setNewState();
}
}
public final class MyActivity extends Activity {
// The activity logic is in mLogic
private final MyActivityLogic mLogic;
// Logic is created in constructor
public MyActivity() {
super();
mLogic = new MyActivityLogic(
(MyApp) getApplicationContext());
}
// Getter, you could make a setter as well, but I leave
// that as an exercise for you
public MyActivityLogic getMyActivityLogic() {
return mLogic;
}
// The method to be tested
public void onClick(View pView) {
mLogic.onClick(pView);
}
// Surely you have other code here...
}
todo debería ser algo como esto: 
Para probar MyActivityLogic
no necesitará utilizar una jUnit simple TestCase
en lugar de ActivityUnitTestCase
(ya que no es una Actividad), y puede simular el contexto de la aplicación utilizando su marco de referencia preferido (ya que manual su propio simulacro es un poco molesto). Ejemplos de uso Mockito:
MyActivityLogic mLogic; // The CUT, Component Under Test
MyApplication mMyApplication; // Will be mocked
protected void setUp() {
// Create the mock using mockito.
mMyApplication = mock(MyApplication.class);
// "Inject" the mock into the CUT
mLogic = new MyActivityLogic(mMyApplication);
}
public void testOnClickShouldSetNewStateOnAppContext() {
// Test composed of the three A's
// ARRANGE: Most stuff is already done in setUp
// ACT: Do the test by calling the logic
mLogic.onClick(null);
// ASSERT: Make sure the application.setNewState is called
verify(mMyApplication).setNewState();
}
Para probar la MyActivity
utiliza ActivityUnitTestCase
como de costumbre, sólo tenemos que asegurarnos de que se crea un MyActivityLogic
con el correcto ApplicationContext
. Ejemplo de código de prueba incompleto que hace todo esto:
// ARRANGE:
MyActivity vMyActivity = getActivity();
MyApp expectedAppContext = vMyActivity.getApplicationContext();
// ACT:
// No need to "act" much since MyActivityLogic object is created in the
// constructor of the activity
MyActivityLogic vLogic = vMyActivity.getMyActivityLogic();
// ASSERT: Make sure the same ApplicationContext singleton is inside
// the MyActivityLogic object
MyApp actualAppContext = vLogic.getMyApp();
assertSame(expectedAppContext, actualAppContext);
Espero que todo tenga sentido para ti y te ayude.
He tenido la idea de reemplazar _getApplicationContext() _ con _getApplication() _. Ahora puedo simular el objeto _Application_ y usar _setApplication() _. Es un poco de solución. Sin embargo, no entiendo la diferencia entre esos métodos. Y la [pregunta] (http://stackoverflow.com/questions/5018545) relacionada con eso no es respondida. – lstipakov