覆盖 Guice 中的绑定

新手上路,请多包涵

我刚开始玩 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 映射时,它会很好地工作接口和实现。

此外,在与同事讨论这个问题之后,我们似乎会走上覆盖整个模块并确保我们正确定义模块的道路。这似乎可能会导致问题,尽管绑定在模块中放错了位置并且需要移动,因此可能会破坏测试负载,因为绑定可能不再可用于被覆盖。

原文由 tddmonkey 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 899
2 个回答

这可能不是您正在寻找的答案,但如果您正在编写单元测试,您可能不应该使用注入器,而应该手动注入模拟或假对象。

另一方面,如果你真的想替换单个绑定,你可以使用 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 的绑定移动到一个单独的模块来实现。

原文由 albertb 发布,翻译遵循 CC BY-SA 4.0 许可协议

为什么不使用继承?您可以在 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());

原文由 Mon Calamari 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题