Acabo de empezar a jugar con Guice, y un caso de uso en el que puedo pensar es que en una prueba solo quiero anular un enlace único. Creo que me gustaría usar el resto de los enlaces de nivel de producción para asegurar que todo esté configurado correctamente y evitar duplicaciones.
Entonces imagina que tengo el siguiente Módulo
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);
}
}
Y en mi prueba solo quiero anular InterfaceC, manteniendo InterfaceA e InterfaceB intactas, así que me gustaría algo como:
Module testModule = new Module() {
public void configure(Binder binder) {
binder.bind(InterfaceC.class).to(MockC.class);
}
};
Guice.createInjector(new ProductionModule(), testModule);
También probé lo siguiente, sin suerte:
Module testModule = new ProductionModule() {
public void configure(Binder binder) {
super.configure(binder);
binder.bind(InterfaceC.class).to(MockC.class);
}
};
Guice.createInjector(testModule);
¿Alguien sabe si es posible hacer lo que quiero o estoy ladrando por completo el árbol equivocado?
--- Seguimiento: Parece que puedo lograr lo que quiero si uso la etiqueta @ImplementedBy en la interfaz y luego solo proporciono un enlace en el caso de prueba, que funciona bien cuando hay un mapeo 1-1 entre La interfaz y la implementación.
Además, después de discutir esto con un colega, parecería que deberíamos anular un módulo completo y asegurarnos de que nuestros módulos estén definidos correctamente. Sin embargo, parece que podría causar un problema cuando un enlace está fuera de lugar en un módulo y necesita ser movido, por lo que posiblemente se rompa una carga de pruebas ya que los enlaces ya no estarán disponibles para anularse.
fuente

Respuestas:
Puede que esta no sea la respuesta que está buscando, pero si está escribiendo pruebas unitarias, probablemente no debería estar usando un inyector y más bien estar inyectando objetos falsos o falsos a mano.
Por otro lado, si realmente desea reemplazar un enlace único, puede usar
Modules.override(..):Ver detalles aquí .
Pero como
Modules.overrides(..)recomienda Javadoc , debe diseñar sus módulos de tal manera que no necesite anular los enlaces. En el ejemplo que dio, puede lograrlo moviendo el enlaceInterfaceCa un módulo separado.fuente
ovveridepierde el correctoStageal hacerlo (es decir, DESARROLLO se usa sistemáticamente).¿Por qué no usar la herencia? Puede anular sus enlaces específicos en el
overrideMemétodo, dejando implementaciones compartidas en elconfiguremétodo.Y finalmente cree su inyector de esta manera:
fuente
@Overrideno parece funcionar. Especialmente si se hace en un método que@Providesalgo.Si no desea cambiar su módulo de producción y si tiene una estructura de proyecto maven predeterminada como
Puede crear una nueva clase
ConcreteCen su directorio de prueba usando el mismo paquete que para su clase original. Guice se unirá entoncesInterfaceCaConcreteCpartir de su directorio de prueba, mientras que todas las demás interfaces se unirán a sus clases de producción.fuente
Desea usar Juckito donde puede declarar su configuración personalizada para cada clase de prueba.
fuente
En una configuración diferente, tenemos más de una actividad definida en módulos separados. La actividad que se está inyectando está en un módulo de biblioteca de Android, con su propia definición de módulo RoboGuice en el archivo AndroidManifest.xml.
La configuración se ve así. En el módulo de biblioteca hay estas definiciones:
AndroidManifest.xml:
Luego tenemos un tipo que se inyecta:
Alguna implementación predeterminada de Foo:
MainModule configura la implementación de FooThing para Foo:
Y finalmente, una actividad que consume Foo:
En el consumo del Módulo de aplicaciones de Android, nos gustaría usar
SomeActivitypero, para fines de prueba, inyectar el nuestroFoo.Se podría argumentar que exponer el manejo del módulo a la aplicación del cliente, sin embargo, necesitamos ocultar principalmente los componentes que se inyectan porque el Módulo de biblioteca es un SDK, y exponer piezas tiene implicaciones más grandes.
(Recuerde, esto es para pruebas, por lo que conocemos los aspectos internos de SomeActivity y sabemos que consume un Foo (paquete visible)).
La forma en que descubrí que funciona tiene sentido; use la anulación sugerida para probar :
Ahora, cuando
SomeActivityse inicia, obtendráOtherFooThingsuFooinstancia inyectada .Es una situación muy específica en la que, en nuestro caso, OtherFooThing se usó internamente para registrar situaciones de prueba, mientras que FooThing se usó, por defecto, para todos los demás usos.
Tenga en cuenta que estamos utilizando
#newDefaultRoboModuleen nuestras pruebas unitarias, y funciona perfectamente.fuente