Acabei de começar a brincar com o Guice, e um caso de uso em que consigo pensar é que, em um teste, quero substituir uma única ligação. Eu acho que gostaria de usar o restante das ligações de nível de produção para garantir que tudo esteja configurado corretamente e para evitar duplicação.
Então imagine que eu tenho o seguinte 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);
}
}
E no meu teste, eu quero apenas substituir a InterfaceC, mantendo a InterfaceA e a InterfaceB intactas, então gostaria de algo como:
Module testModule = new Module() {
public void configure(Binder binder) {
binder.bind(InterfaceC.class).to(MockC.class);
}
};
Guice.createInjector(new ProductionModule(), testModule);
Eu também tentei o seguinte, sem sorte:
Module testModule = new ProductionModule() {
public void configure(Binder binder) {
super.configure(binder);
binder.bind(InterfaceC.class).to(MockC.class);
}
};
Guice.createInjector(testModule);
Alguém sabe se é possível fazer o que eu quero ou estou latindo completamente na árvore errada?
--- Acompanhamento: parece que posso conseguir o que quero se fizer uso da tag @ImplementedBy na interface e fornecer apenas uma ligação no caso de teste, o que funciona bem quando há um mapeamento 1-1 entre a interface e implementação.
Além disso, depois de discutir isso com um colega, parece que seguiríamos no caminho de substituir um módulo inteiro e garantir que nossos módulos estejam definidos corretamente. Parece que isso pode causar um problema, embora uma ligação seja extraviada em um módulo e precise ser movida, possivelmente interrompendo uma carga de testes, pois as ligações podem não estar mais disponíveis para serem substituídas.
fonte
Respostas:
Pode não ser a resposta que você está procurando, mas se estiver escrevendo testes de unidade, provavelmente não deve usar um injetor e sim injetar objetos falsos ou falsos à mão.
Por outro lado, se você realmente deseja substituir uma única ligação, pode usar
Modules.override(..)
:Veja detalhes aqui .
Mas, como
Modules.overrides(..)
recomenda o javadoc for , você deve projetar seus módulos de forma que não precise substituir ligações. No exemplo que você deu, você pode conseguir isso movendo a ligação deInterfaceC
para um módulo separado.fonte
ovveride
perde o devidoStage
ao fazê-lo (isto é, o DESENVOLVIMENTO é usado sistematicamente).Por que não usar herança? Você pode substituir suas ligações específicas no
overrideMe
método, deixando implementações compartilhadas noconfigure
métodoE, finalmente, crie seu injetor desta maneira:
fonte
@Override
parece não funcionar. Especialmente se for feito em um método que@Provides
algo.Se você não deseja alterar seu módulo de produção e se possui uma estrutura de projeto padrão semelhante a um maven, como
Você pode apenas criar uma nova classe
ConcreteC
no seu diretório de teste usando o mesmo pacote da sua classe original. O Guice será vinculadoInterfaceC
aoConcreteC
diretório de teste, enquanto todas as outras interfaces serão vinculadas às suas classes de produção.fonte
Você deseja usar o Juckito, onde pode declarar sua configuração personalizada para cada classe de teste.
fonte
Em uma configuração diferente, temos mais de uma atividade definida em módulos separados. A atividade que está sendo injetada está em um Android Library Module, com sua própria definição de módulo RoboGuice no arquivo AndroidManifest.xml.
A configuração é assim. No módulo Library, existem estas definições:
AndroidManifest.xml:
Então temos um tipo sendo injetado:
Alguma implementação padrão do Foo:
MainModule configura a implementação do FooThing para o Foo:
E, finalmente, uma atividade que consome Foo:
No consumidor Android Application Module, gostaríamos de usar
SomeActivity
, mas, para fins de teste, injetar o nossoFoo
.Alguém pode argumentar para expor o manuseio do módulo ao aplicativo cliente, no entanto, precisamos ocultar principalmente os componentes que estão sendo injetados porque o Módulo Biblioteca é um SDK, e a exposição de peças tem implicações maiores.
(Lembre-se, isso é para teste, por isso conhecemos os elementos internos do SomeActivity e sabemos que ele consome um Foo (pacote visível)).
A maneira como descobri que funciona faz sentido; use a substituição sugerida para testar :
Agora, quando
SomeActivity
iniciado, ele obteráOtherFooThing
suaFoo
instância injetada .É uma situação muito específica em que, no nosso caso, o OtherFooThing foi usado internamente para registrar situações de teste, enquanto o FooThing foi usado, por padrão, para todos os outros usos.
Lembre-se de que estamos usando
#newDefaultRoboModule
nossos testes de unidade e funciona perfeitamente.fonte