通过拦截器或监听器或预处理器

时间:2016-11-11 15:59:11

标签: java dependency-injection binding mocking guice

我想知道Guice是否有办法在创建之前通过使用侦听器或拦截器来覆盖绑定。

我的情景是:

我有一个绑定客户端的模块A,例如:

public static class ProdModule extends AbstractModule {
        @Override
        protected void configure() {
            bind(Client.class).toInstance(ClientBuilder.newBuilder().build());
        }
    }

这种绑定需要被嘲笑。因此,我希望测试添加一个注册监听器(或其他东西)的新模块,这样当Guice尝试解析该绑定时,我可以用我想要的任何绑定替换它。

我知道Modules.override(...)但是这不能用于我的设置。实例化Injector的代码基本上隐藏在依赖中。我无权更改代码以使用模块覆盖,但是我可以添加任意数量的新模块。

我不想替换整个模块,也不想更改模块代码。

我一直在尝试一些不起作用的东西,或者我不确定如何使用它们:

我尝试使用ProvisionListener。这有点“有点”。我可以通过使用反射并更改Provision上的结果字段来覆盖特定的提供者。这不适用于绑定实例。

我尝试使用ElementVisitorBindingTargetVisitor,但他们并没有真正为我做任何事情。我可能无法准确理解这两位访问者的目的是什么,而且我没有找到太多的文档或示例。

1 个答案:

答案 0 :(得分:1)

似乎你正在向后解决这个问题 - 依赖注入存在于启用测试,所以如果你在使用DI框架时努力编写可测试的代码,那么值得退一步并计算在更高层次上出了什么问题,而不是试图让框架按照你认为应该的方式行事。

此绑定需要被模拟。”是一个大红旗。您几乎不需要绑定mocks对象,因为模拟很脆弱,通常用于单用途单元测试,而不是跨应用程序的DI框架提供。

如果您正在编写单元测试,则根本不需要框架 - 只需在测试中直接实例化,传入必要的模拟。感谢依赖注入,如果所有依赖项都被模拟掉,你应该能够快速单独测试一个类 - 不需要框架。

如果您正在编写集成或其他更大的测试,因此需要构建一个注入器并对系统进行整体测试,那么理想情况下应该对无法安全测试的组件进行伪造(非模拟)实现,并且用于此类测试的备用模块。例如,您的测试注入器将安装FakeCreditCardProcessorModule而不是CreditCardProcessorModule,并且提供您尝试测试的绑定的模块松散耦合到不关心安装哪个处理器模块。如果由于过度耦合的模块而不是一个选项,Modules.override()可用于伪造单个绑定。

只有当你正在测试一个模块的逻辑本身时,你才想要绑定模拟(尽管通常不会在模块中使用复杂的逻辑测试测试)。您应该安装 正在测试的模块,以及一个单独的模块,该模块将模拟绑定到任何所需的绑定。这是使用DI框架模拟真正有意义的唯一时间。

如果上述方案均不适用,请提供有关您正在尝试测试的 的更多详细信息。