2017-04-06 2 views
1

J'utilise Espresso pour tester un Activity qui affiche les données récupérées en utilisant un ContentProvider.Comment utiliser MockContentResolver lors du test d'une activité Android avec Espresso?

J'aimerais se moquer du fournisseur de contenu en utilisant MockContentProvider et MockContentResolver, mais je ne sais pas comment faire la méthode d'activité getContentResolver() retour d'un résolveur simulé.

(je pourrais insérer les données avant d'exécuter le test, mais je voudrais savoir s'il est possible d'utiliser un fournisseur fictif à la place)

MISE À JOUR: Je ne pouvais pas faire encore travailler, donc je J'inclus un code pour essayer de le rendre plus clair.

MyActivity.java

MyActivity extends AppCompatActivity { 

    ... 

    private delete(String id) { 
     // The method getContentResolver() is what I want to mock when testing 
     getContentResolver().delete(
      Contract.Item.makeUriForItem(id), null, null); 
    } 

    ... 

} 

MyActivityTests.java

@RunWith(AndroidJUnit4.class) 
@LargeTest 
public class StockChartDetailsActivityTests { 

    @Rule 
    public ActivityTestRule<MyActivity> myActivityTestRule = new ActivityTestRule<MyActivity>(
     MainActivity.class); 

    @Test 
    public void test() { 

    } 

} 

Je ne pouvais pas faire la suggestion d'utiliser Dagger2 travailler parce que getContentResolver() est mis en œuvre par Android et je ne peux pas utiliser @Inject pour injecter mon propre ContentResolver.

Je pourrais utiliser différentes stratégies:

  • données dans la base de données à insérer avant l'essai.
  • avoir une autre couche, comme une couche logique métier, et déplacer les appels vers getContentResolver() vers les classes de cette couche, puis injecter (et mocker) les classes de logique métier.

Mais avant d'utiliser l'une de ces stratégies, j'aimerais savoir s'il est possible d'utiliser MockContentResolver.

+0

S'il vous plaît inclure un exemple de code avec votre question. –

Répondre

2

Vous devez utiliser une structure d'injection de dépendances. Je pense que pour Android, un bon choix est Dagger 2. Avec Dagger, vous pouvez injecter dans votre Activity votre véritable fournisseur de contenu. Une manière courante d'injecter quelque chose dans une activité est d'utiliser une injection de champ (car vous ne pouvez pas agir directement sur le constructeur de l'activité: elle est créée par le système). Vous pouvez donc instancier le module Dagger dans la classe Application et l'obtenir à partir du Activity pour vous injecter. Quelque chose comme:

((MyApplication).getMyComponent()).inject(this); 

Votre classe MyApplication contiendra quelque chose comme:

MyComponent mMyComponent = DaggerMyComponent.builder() 
       .appModule(new AppModule(this)) // this is in general useful if you need a Context 
       .contentProviderModule(new ContentProviderModule()) 
       .build(); 

Et il doit inclure bien sûr la méthode getMyComponent() pour le retour du module:

MyComponent getMyComponent() { 
    return mMyComponent; 
} 

Maintenant que votre module est injecté dans votre activité de l'extérieur, vous pouvez facilement injecter autre chose à des fins de test:

Dans le dossier/test/et en utilisant le même chemin que votre classe MyApplication, vous pouvez créer une nouvelle classe qui étend MyApplication et crée votre module en transmettant une version simulée du ContentProvider.

Je ne peux pas passer par toutes les étapes, mais vous pouvez jeter un oeil here pour plus de détails

+0

Consultez également le travail de Chiu-ki Chan. Elle utilise Mockito et implémente un coureur personnalisé pour instancier une application fictive. http://blog.sqisland.com/2015/04/dagger-2-espresso-2-mockito.html https://youtu.be/JlHJFZvZyxw?t=23m38s –

+0

Puis-je injecter quelque chose qui fait partie du framework Android? , @ GVillani82? Ce que j'essaie de mocker, c'est ContentResolver auquel j'ai accès en appelant la méthode getContentResolver() sur un contexte. –

+0

Oui, vous avez besoin d'un contexte. C'est ainsi que je vous suggère d'utiliser un autre module (AppModule) qui injecte le contexte de l'application. [Ici] (https://github.com/codepath/android_guides/wiki/Dependency-Injection-with-Dagger-2) vous pouvez trouver sa mise en œuvre – GVillani82