【问题标题】:DI with auto-generated web service clients具有自动生成的 Web 服务客户端的 DI
【发布时间】:2014-03-04 02:02:46
【问题描述】:

我正在尝试在整个应用层进行依赖注入,并且遇到了我确信其他人已经看到的场景。我们使用了一些第三方 Web 服务,并且客户端是使用基类自动生成的。客户端没有接口,数据类型在同一个文件/项目中。

明显的问题是,如果我想进行单元测试,我需要模拟服务。我需要提取一个接口并将数据类型移动到一个可供真实/模拟客户使用的“合同”项目中。但是,下次自动生成客户端时,需要重做工作。在运行时创建代理不会有太大帮助,因为那时我们将不得不从 WSDL 手动创建接口和数据类型。有没有更好的方法来处理这个问题?

【问题讨论】:

  • 在这种情况下,通过 Microsoft Fakes 的垫片对您有用吗? msdn.microsoft.com/en-us/library/hh549175.aspx
  • @BrendanGreen - 为我今天学到的新知识 +1。这可能可行,但是由于我可以控制客户端代码,因此我想尽可能避免走这条路。绝对是一个值得记住的好工具。

标签: c# web-services unit-testing dependency-injection


【解决方案1】:

无论如何,从实现中提取接口对您没有多大帮助,因为这将是一个糟糕的抽象。

接口应该由使用接口的客户端定义和拥有。正如Agile Principles, Patterns, and Practices 解释的那样,“客户 […] 拥有抽象接口”(第 11 章)。因此,任何尝试定义以数据为中心的接口(例如从自动生成的 Web 服务客户端提取接口)迟早都会导致问题,因为它违反了各种 SOLID 原则,例如依赖倒置原则或接口隔离原则。

相反,您的客户端代码应该定义他们需要的接口。然后,您始终可以实现这些接口与自动生成的 Web 服务客户端。如果您使用过 Microsoft 的工具(Visual Studio、wsdl.exe 等),则相关的自动生成的类应该已经是 partial class,这意味着您应该能够在没有触摸它的自动生成部分。

【讨论】:

  • 试图理解......为什么提取接口会违反DI原则?其余代码将仅引用接口,并且实例可以由 IoC 容器提供。我理解接口隔离,因为提取接口可能会导致不需要的成员,但如果您可能使用服务提供的大部分/全部内容,它可以用作起点并清理它。
  • 关于拥有接口和分部类的客户端,您是说我应该在分部类中添加业务逻辑以从接口映射到服务实际提供的内容吗?这是一个有趣的概念,因此依赖于接口的代码在服务更改时不一定需要更改,但如果它变得足够复杂,我想测试该业务逻辑,我马上回到我开始的地方。
  • DIP 说“抽象不应该依赖于细节。细节应该依赖于抽象。”如果接口与服务定义在同一个包中,则客户端依赖于服务包(实现细节)。这就是为什么 DIP 声明客户端应该拥有他们需要的接口。是的,您可能需要测试转换逻辑,但这不是业务逻辑,这是实现细节的一部分。业务逻辑应该是独立的包:blog.ploeh.dk/2013/12/03/…
  • 对,接口将进入单独的合同包/项目中。您引用的第 11 章还提到了以下几段。它还说“客户端倾向于拥有抽象接口,并且他们的服务器从它们派生。”但是,在这种情况下,服务已经定义,并且不太可能有多个服务实现此接口,尽管我明白你关于转换逻辑的观点。无论如何,这都是很好的信息,让我更好地了解该走哪条路。
  • 可爱,我刚刚看到你是 AutoFixture 的创造者,它是我的原型列表中的下一个。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-18
  • 2016-11-15
  • 2015-09-09
  • 2010-12-31
  • 1970-01-01
  • 2013-07-27
  • 2012-05-19
相关资源
最近更新 更多