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 enlaceInterfaceC
a un módulo separado.fuente
ovveride
pierde el correctoStage
al hacerlo (es decir, DESARROLLO se usa sistemáticamente).¿Por qué no usar la herencia? Puede anular sus enlaces específicos en el
overrideMe
método, dejando implementaciones compartidas en elconfigure
método.Y finalmente cree su inyector de esta manera:
fuente
@Override
no parece funcionar. Especialmente si se hace en un método que@Provides
algo.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
ConcreteC
en su directorio de prueba usando el mismo paquete que para su clase original. Guice se unirá entoncesInterfaceC
aConcreteC
partir 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
SomeActivity
pero, 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
SomeActivity
se inicia, obtendráOtherFooThing
suFoo
instancia 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
#newDefaultRoboModule
en nuestras pruebas unitarias, y funciona perfectamente.fuente