2017-08-18 27 views
1

假设我们有一个CreditCardService微服务,它依赖于使用JSON进行通信的ThreeDSecureService微服务。微服务合同的自动化测试?

ThreeDSecureService的API(或甚至实施)的微小变化可能会悄悄地破坏CreditCardService(和其他潜在客户端)。所以,我们希望自动化测试。

我看到两个有缺陷的方法,并且想知道如何改进。

  1. 在ThreeDSecureService.Tests中进行集成测试。

随附的ThreeDSecureService测试项目可以通过固定的JSON输入进行集成测试。伪装任何依赖关系,它可以运行一个完全的输入调用,确认服务吞下输入。

这里的问题是,如果有人未能意识到他们的变化会如何破坏客户端,他们几乎可以“修复”测试来匹配他们的变化。

  1. CreditCardService.Tests中的集成测试。

客户端是实际上想要测试有关ThreeDSecureService预期输入的断言的人。但是,这需要客户端解决方案包含ThreeDSecureService项目以及它所依赖的任何项目。这会否定我们从使用微服务中获得的许多优势!

我们如何在不破坏我们从使用微服务中获得的松散耦合的情况下从客户端断言(维护依赖关系)?

+1

难道你不能简单地让你的集成测试项目了解它们吗(通过引用或以某种方式启动它们)?这两个服务不需要彼此了解,但是我认为在引用它们的测试项目中没有任何伤害。 – kkirk

+0

在此阅读我的答案:https://stackoverflow.com/a/45177810/569662。 OP有关于如何管理服务依赖关系的类似问题。 –

+0

@kkirk但是,当您在处理客户端项目时,您需要运行常规测试。因此,您需要将集成测试项目包含在客户端解决方案中,否?如果我们可以引用依赖关系的DLL *,那就好了......但是我们如何保持最新的,即最新的和构建的? – Timo

回答

0

为避免突破集成,请使用公共合同。例如,RAML。描述特定服务的客户将获得并通过的模型,描述操作和参数。在这种情况下,没有人依赖于特定的服务或实施,双方都需要测试他们与合同的沟通。

额外的安全措施将发布您的合同作为DLL。在这种情况下,服务的消费者会在一分钟内注意到变化。如果他们有单元测试,他们可能会更早地显示任何问题。

作为一个保持分离的主要规则:不要参考实现,而是引用契约。

1

我希望我能理解你所问的内容,但如果不是这样,以下内容至少对你的思维有所贡献。

我理解你的问题的方式是一个非常实用的方法,即“如何组织解决方案和项目,以最大限度地降低开发人员违反服务合同而不理解其对服务消费者的影响的风险?”

在理想的世界中,开发人员不这样做。如果他们对服务进行了重大更改,他们知道他们已经完成了,而且这是一个新版本。这就是说,我明白你的观点 - 很高兴能有一些抵御这种人为错误的保护措施,因为开发人员大多数时间都是完美的。

如果您正在一个环境中工作,您正在创建其他团队依赖的微服务,反之亦然,那么就没有办法遵循严谨和结构化的方法,即适当的治理。一个能够反映生产的完整测试环境,所有服务都在运行,并且您可以测试您的服务与其所依赖的服务的集成情况,但这并不会造成任何影响。

如果你在控制所有需要彼此通信的服务,那么(至少在我看来)没有理由不应该有一个解决方案,即你所有的服务项目都包含在哪里以及哪里您的集成测试项目将启动所需的所有服务,并检查它们之间的集成是否按预期工作。

除了契约/接口之外,您的个人微服务不应该知道外界的任何信息,您应该有单元测试来独立地测试每个微服务,嘲笑依赖关系。

如果一个解决方案变得太大,您可以将其分解为更小的部分,以便为每个包含该服务及其最近邻居的服务提供一个解决方案。在你的例子中,这可能是一个包含ThreeDSecureService,CreditCardService和CreditCardService.IntegrationTests(它测试CreditCardService,然后调用ThreeDSecureService)的解决方案。 这样,当开发人员开发ThreeDSecureService时,集成测试将让开发人员知道他/她已经破坏了集成。 这仍然需要开发人员记住当然实际运行Integration测试。

我认为它的最终目标是在构建流程中加入一个门,以确保开发人员无法发布会导致集成测试失败并与自动部署相结合的更改。这将确保基本的整合错误不会使其投入生产。

+0

我喜欢读这本书。 :)你会如何建议微服务“知道”合同?目前,他们有自己的序列化模型,*假设*他们所调用的服务仍然遵守该合同。 **我的目标是,如果这些合同改变了**(通常意味着有人搞砸了),就会提前发出警告。合同应该易于维护,并且在解决方案管理方面增加很少的开销。 – Timo

+0

太棒了,我很高兴这很有用。我建议在NuGet软件包或类似软件中定义合同的接口,这些接口是版本化的,以便您确切知道每个服务实现的合约。我通过为每个服务定义一个单独的命名空间来处理服务的版本控制,例如CreditCardService.v1_0,CreditCardService.v1_1等。 您可以对独立的NuGet包中的数据模型执行相同的操作,NuGet包依赖于该包。 这样,当所有服务都在相同版本的包上时,它们对每个数据模型都有完全相同的理解。 – kkirk

+0

有趣的想法。我也在考虑类似的选择,比如只用契约来引用DLL,或者有一个大的Contracts项目(塞满界面)被所有东西引用。我将不得不调查每个的利弊。 – Timo