Je viens de commencer à jouer avec Guice, et un cas d'utilisation auquel je peux penser est que dans un test, je veux juste remplacer une seule liaison. Je pense que j'aimerais utiliser le reste des liaisons au niveau de la production pour m'assurer que tout est correctement configuré et éviter la duplication.
Alors imaginez que j'ai le module suivant
public class ProductionModule implements Module {
public void configure(Binder binder) {
binder.bind(InterfaceA.class).to(ConcreteA.class);
binder.bind(InterfaceB.class).to(ConcreteB.class);
binder.bind(InterfaceC.class).to(ConcreteC.class);
}
}
Et dans mon test, je veux seulement remplacer InterfaceC, tout en gardant InterfaceA et InterfaceB intacts, donc je voudrais quelque chose comme:
Module testModule = new Module() {
public void configure(Binder binder) {
binder.bind(InterfaceC.class).to(MockC.class);
}
};
Guice.createInjector(new ProductionModule(), testModule);
J'ai également essayé ce qui suit, sans succès:
Module testModule = new ProductionModule() {
public void configure(Binder binder) {
super.configure(binder);
binder.bind(InterfaceC.class).to(MockC.class);
}
};
Guice.createInjector(testModule);
Est-ce que quelqu'un sait s'il est possible de faire ce que je veux ou est-ce que j'aboie complètement le mauvais arbre?
--- Suivi: Il semblerait que je puisse réaliser ce que je veux si j'utilise la balise @ImplementedBy sur l'interface et que je fournis simplement une liaison dans le cas de test, ce qui fonctionne bien quand il y a un mappage 1-1 entre l'interface et la mise en œuvre.
De plus, après en avoir discuté avec un collègue, il semblerait que nous prenions la route pour remplacer un module entier et nous assurer que nos modules sont définis correctement. Cela semble cependant causer un problème lorsqu'une liaison est mal placée dans un module et doit être déplacée, ce qui peut éventuellement interrompre une charge de tests car les liaisons peuvent ne plus être disponibles pour être remplacées.
la source
Réponses:
Ce n'est peut-être pas la réponse que vous recherchez, mais si vous écrivez des tests unitaires, vous ne devriez probablement pas utiliser d'injecteur et plutôt injecter des objets factices ou faux à la main.
En revanche, si vous souhaitez vraiment remplacer une seule liaison, vous pouvez utiliser
Modules.override(..)
:Voir les détails ici .
Mais comme le javadoc pour le
Modules.overrides(..)
recommande, vous devez concevoir vos modules de telle manière que vous n'ayez pas besoin de remplacer les liaisons. Dans l'exemple que vous avez donné, vous pouvez accomplir cela en déplaçant la liaison deInterfaceC
vers un module distinct.la source
ovveride
perd le bonStage
en le faisant (ie DÉVELOPPEMENT est systématiquement utilisé).Pourquoi ne pas utiliser l'héritage? Vous pouvez remplacer vos liaisons spécifiques dans
overrideMe
method, laissant les implémentations partagées dansconfigure
method.Et enfin créez votre injecteur de cette façon:
la source
@Override
ne semble pas fonctionner. Surtout si c'est fait sur une méthode que@Provides
quelque chose.Si vous ne souhaitez pas modifier votre module de production et si vous avez une structure de projet de type maven par défaut comme
Vous pouvez simplement créer une nouvelle classe
ConcreteC
dans votre répertoire de test en utilisant le même package que pour votre classe d'origine. Guice se liera alorsInterfaceC
àConcreteC
partir de votre répertoire de test tandis que toutes les autres interfaces seront liées à vos classes de production.la source
Vous souhaitez utiliser Juckito où vous pouvez déclarer votre configuration personnalisée pour chaque classe de test.
la source
Dans une configuration différente, nous avons plus d'une activité définie dans des modules séparés. L'activité qui est injectée se trouve dans un module de bibliothèque Android, avec sa propre définition de module RoboGuice dans le fichier AndroidManifest.xml.
La configuration ressemble à ceci. Dans le module Bibliothèque, il y a ces définitions:
AndroidManifest.xml:
Ensuite, nous avons un type en cours d'injection:
Une implémentation par défaut de Foo:
MainModule configure l'implémentation FooThing pour Foo:
Et enfin, une activité qui consomme Foo:
Dans le module d'application Android, nous aimerions utiliser
SomeActivity
mais, à des fins de test, injectons le nôtreFoo
.On pourrait argumenter pour exposer la gestion du module à l'application cliente, cependant, nous devons principalement masquer les composants en cours d'injection car le module de bibliothèque est un SDK et l'exposition de pièces a des implications plus importantes.
(Rappelez-vous, c'est pour les tests, donc nous connaissons les composants internes de SomeActivity, et savons qu'il consomme un (package visible) Foo).
La façon dont j'ai trouvé que cela fonctionne a du sens; utilisez le remplacement suggéré pour les tests :
Maintenant, au
SomeActivity
démarrage, il obtiendraOtherFooThing
pour sonFoo
instance injectée .C'est une situation très spécifique où, dans notre cas, OtherFooThing a été utilisé en interne pour enregistrer des situations de test, tandis que FooThing a été utilisé, par défaut, pour toutes les autres utilisations.
Gardez à l' esprit, nous sommes utilisons
#newDefaultRoboModule
dans nos tests unitaires, et il fonctionne parfaitement.la source