我刚开始玩Guice,我能想到的一个用例是在测试中我只想覆盖单个绑定.我想我想使用其余的生产级别绑定来确保正确设置所有内容并避免重复.
所以想象我有以下模块
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); } }
在我的测试中,我只想覆盖InterfaceC,同时保持InterfaceA和InterfaceB,所以我想要像:
Module testModule = new Module() { public void configure(Binder binder) { binder.bind(InterfaceC.class).to(MockC.class); } }; Guice.createInjector(new ProductionModule(), testModule);
我也试过以下,没有运气:
Module testModule = new ProductionModule() { public void configure(Binder binder) { super.configure(binder); binder.bind(InterfaceC.class).to(MockC.class); } }; Guice.createInjector(testModule);
有谁知道是否有可能做我想做的事情,或者我完全咆哮错误的树?
---跟进:如果我在接口上使用@ImplementedBy标记,然后在测试用例中提供一个绑定,看起来我可以实现我想要的,当它之间存在1-1映射时,它可以很好地工作界面和实现.
此外,在与同事讨论之后,似乎我们将推翻覆盖整个模块并确保正确定义模块.这似乎可能会导致问题,虽然绑定在模块中放错位置并需要移动,因此可能会破坏大量测试,因为绑定可能不再可用于覆盖.
这可能不是您正在寻找的答案,但如果您正在编写单元测试,您可能不应该使用注入器而是手动注入模拟或伪造对象.
另一方面,如果您真的想要替换单个绑定,可以使用Modules.override(..)
:
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); } } public class TestModule implements Module { public void configure(Binder binder) { binder.bind(InterfaceC.class).to(MockC.class); } } Guice.createInjector(Modules.override(new ProductionModule()).with(new TestModule()));
详情请见此处.
但是作为Modules.overrides(..)
推荐的javadoc ,您应该以不需要覆盖绑定的方式设计模块.在您给出的示例中,您可以通过将绑定移动InterfaceC
到单独的模块来实现.
为什么不使用继承?您可以在overrideMe
方法中覆盖特定绑定,在方法中保留共享实现configure
.
public class DevModule implements Module { public void configure(Binder binder) { binder.bind(InterfaceA.class).to(TestDevImplA.class); overrideMe(binder); } protected void overrideMe(Binder binder){ binder.bind(InterfaceC.class).to(ConcreteC.class); } }; public class TestModule extends DevModule { @Override public void overrideMe(Binder binder) { binder.bind(InterfaceC.class).to(MockC.class); } }
最后以这种方式创建您的注入器:
Guice.createInjector(new TestModule());