2016-05-08 22 views
2

Ich benutze seit kurzem Dagger 2, um die Abhängigkeiten meiner App zu verwalten. Um einige Klassen testbar zu machen, habe ich angefangen, viele Klassen zu erstellen, die ich injizieren muss. Ich konnte das machen, aber der Prozess, um diese neuen Klassen zu bekommen, sieht für mich etwas kompliziert aus. Nehmen wir ein Beispiel:Was ist der beste Weg Subklassen mit Dagger 2 zu injizieren?

Ich möchte zum Beispiel die Methode onCreateViewHolder() von meinem RecyclerViewAdapter testen. Dazu habe ich eine Fabrik erstellt, die die ViewHolder auf der gegebenen LayoutType basiert zurückgibt:

public class ViewHolderFactor { 

    public RecyclerView.ViewHolder getViewHolder(ViewGroup parent, int viewType) { 
     LayoutInflater inflater = this.getLayoutInflater(parent.getContext()); 
     View view; 
     switch (LayoutType.fromInteger(viewType)) { 
      case SMALL_VERTICAL: 
       view = inflater.inflate(R.layout.rsc_util_item_small, parent, false); 
       return new ViewHolder.ItemViewHolder(view); 
      case LARGE_VERTICAL: 
       view = inflater.inflate(R.layout.rsc_util_item_large, parent, false); 
       return new ViewHolder.ItemViewHolder(view); 
     } 
     return null; 
    } 

    private LayoutInflater getLayoutInflater(Context context) { 
     return LayoutInflater.from(context); 
    } 

} 

Durch den obigen Code zu einer getrennten Klasse bewegen, ich bin in der Lage zu meiner Einheit Test durchführen mit:

Problem ist: Jetzt, um die App arbeiten zu lassen, muss ich auch die Fremdklasse injizieren, die eine Instanz an den Faktor hält (etwas, was ich nicht getan habe, bevor ich ViewHolderFactor erstellt habe). Am Ende werde ich eine Dolch Konfiguration wie das hat:

@Module 
public class ModuleBusiness { 
    @Provides 
    public CharacterUIService provideCharacterService(Picasso picasso, NotificationUtil notificationUtil, ViewHolderFactor viewHolderFactor) { 
     return new CharacterUIService(picasso, notificationUtil, viewHolderFactor); 
    } 
} 

Wo CharacterUIService ist die Klasse, die eine neue Instanz des RecyclerViewAdapter erzeugt, den die ViewHolderFactory enthält.

public class 
    private ViewHolderFactor 
    @Inject 
    public CharacterUIService(ViewHolderFactor viewHolderFactor) { 
     this.mViewHolderFactor = viewHolderFactor; 
    } 

    // ... 
} 

Ich brauche ein Mitglied von ViewHolderFactor, um es zu injizieren.

Meine Sorgen betrachten die Notwendigkeit, neue globale Variablen zu erstellen und die Anzahl der Parameter, die im Konstruktor übergeben werden, zu erhöhen. Gibt es eine bessere Möglichkeit, diese Unterklassen zu injizieren, oder kann ich es als eine gute Übung betrachten, Unit-Tests zuzulassen?

+1

BTW: Wort "Faktor" ist ziemlich weit von "Fabrik" in Englisch, so dass Sie möglicherweise in Betracht ziehen, Ihre Code-Formulierung zu korrigieren. –

+0

Sie haben Recht, es war Miss tippen. bereits behoben –

Antwort

1

kann ich es als eine gute Praxis betrachten, Unit-Tests zuzulassen?

allererst — in meiner persönlichen Meinung — denke ich, dass Sie die Prüfung übertreiben. In dem Testfall, den Sie zur Verfügung gestellt haben, testen Sie grundsätzlich das Android-Framework selbst. Wenn Sie die Factory testen möchten, sollten Sie testen, ob ein kleines oder großes Element zurückgegeben wird, und nicht, dass die Ansicht nicht null ist.

Aber ja, Ihr scheint ein vernünftiger Ansatz, um Unit-Tests zu ermöglichen.

Wo CharacterUIService die Klasse, die eine neue Instanz der

RecyclerViewAdapter schafft

Sie möchten vielleicht die Rolle von CharacterUIService zu überdenken. "Das schafft eine neue Instanz" klingt nach etwas, das lieber von Dolch gehandhabt werden sollte, da Sie es bereits benutzen.

müssen auch die outter Klasse injizieren, die

Warum eine Instanz in die Fabrik hält? ViewHolderFactor (sic!) Hat selbst keine Abhängigkeiten. Und selbst wenn, was hält dich davon ab, es einfach mit Dolch zu erschaffen und zu injizieren?

class ViewHolderFactor { 
    @Inject 
    ViewHolderFactor() { // allow for constructor injection 
    } 
} 

class YourAdapter { 
    ViewHolderFactor mFactor; 

    @Inject // allow for constructor injection 
    YourAdapter (ViewHolderFactor factor) {/**/} 
} 
// now dagger knows how to create that adapter 

Und nur erstellen lassen Dolch diesen Adapter erstellen?


Und in der Regel, wenn Sie Konstruktor Injektion unterstützen, dann können Sie Ihre @Provides providesSomething() Methoden entfernen. Entfernen Sie einfach die gesamte Methode. Sie haben eine @Inject Annotation für den Konstruktor, also nutzen Sie diese und lassen Sie Dolch diesen Code für Sie schreiben.

// CharacterUIService can be constructor injected. 
@Provides // DAGGER WILL DO THIS FOR YOU 
public CharacterUIService provideCharacterService(Picasso picasso, NotificationUtil notificationUtil, ViewHolderFactor viewHolderFactor) { 
    // REMOVE ALL OF THIS. 
    return new CharacterUIService(picasso, notificationUtil, viewHolderFactor); 
} 

So, während ich denke, Sie machen einen guten Job, indem Sie Dinge testbar zu machen, sollten Sie noch einmal einen guten Blick auf Dolch, da Sie offensichtlich viele Dinge mischen werden. Schauen Sie sich die Konstruktoreinspritzung gut an und nutzen Sie sie, es erspart Ihnen eine Menge Arbeit.

+0

Vielen Dank, ich muss einen besseren Blick auf Dagger werfen und Ihre Kommentare haben mir geholfen. –