我正在编写一个应该处理与第三方API通信的消息传递层。 API有一堆类,在测试工具中不能轻易(如果有的话)实例化。我决定使用适配器/包装器在单元测试中包装我需要的每个类,并通过此适配器类公开我需要的成员。我经常需要通过将它作为对象公开来暴露包装类型。我还为每个或适配器类提供了一个接口,以便能够将它们与模拟框架一起使用。这样我可以用测试中的类代替我需要的东西。缺点是我有一堆适配器类,到目前为止服务器没有其他原因,但测试。对我来说,这本身就是一个很好的理由,但其他人可能会发现这还不够。可能,当我为另一个第三方供应商的API编写实现时,我可能能够重用我的大部分代码,并且只提供特定于供应商API的适配器。但是,这有点长,我不确定它会起作用。
你怎么看?这种方法是可行的还是我编写的不必要的代码没有真正的用途?让我说我确实想为我的消息传递层编写单元测试,但我现在知道如何做它。编辑:
正如一些答案中所建议的那样,我确实使用了IoC / DI。这就是为什么我有适配器类接口的主要原因。
编辑:
我也不喜欢暴露被包裹的物体。我这样做的原因是一些包装类型需要访问其他包装类型。例如。我有一个第三方MessageProducer需要第三方Message对象来发送它。我已将这两种类型包装在适配器中,并尽可能使用适配器。不幸的是,在某些情况下,这是不可能的。
答案 0 :(得分:1)
而不是一堆接口和类。为所有接口创建一组接口和一个实现类。
我想这第三方不遵循告诉不要求政策。它可能会弹出很多州。
尝试将所有第三方状态保留在实现类中。不要让它泄漏通过接口。
请记住,接口将是角色而不是对象。
您写道:我经常需要公开包装类型,并将其作为对象公开。 这是错误的!
我能想到的最好的例子是数据模式数据网关,除了您将使用第三方网关。
不要向第三方公开任何内容。如果你需要某种数据对象。将第三方对象转换为您自己的对象并使用它。
[编辑] 关于需要3rdParty消息的3rdParty消息生产者的评论正是我所说的包装。如果您使用使用关系数据库的数据网关。让我们说我们想在数据库中找到一个项目。我的模型不创建SQL然后查询数据库。相反,我使用了一个接口角色:itemGateway.find(index)。现在在find方法中我们将生成SQL并在数据库上执行连接/查询/关闭。因此,在单元测试中,您可以在模型中测试find时模拟网关。这就是我所说的战斗训练。真正困难的部分现在来自操作编程狗屎(黑客帝国)。然后,您可以通过网关进行测试。这将是我测试的方式。我的网关需要大约三到四个对象(如果你的模式很复杂,第四个就是配置来获取表)。其他三个角色对象是SQLBuilder,DataReader和DB。这些都可以被模拟,以便您可以验证接口调用的交互。所以在这个例子中你需要所有三个对象。
sql = sqlBuilder.buildItemFind(table, index);
db.executeQuery(sql);
reader = reader.setresult(db.result);
return reader.item();
在itemGateway.save(data)的示例中,您只需要SQLBuilder和数据库。
答案 1 :(得分:1)
某些框架(NMock2,Rhino Mocks和TypeMock肯定)可以通过创建从这些类型继承的代理来模拟具体类型而不是接口 - 所以要做到这一点,你的第三方API方法必须是虚拟的,这些课程无法封存。
否则您没有任何选择:如果您想对依赖于这些API的类进行单元测试,则必须创建适配器接口和包装器。
答案 2 :(得分:0)
从另一方面尝试这种方法。将类减少到可以“新建”的实用程序类并测试功能。然后创建轻量级适配器以使用应用程序中的类。
另一种方法是将类与其依赖项分离,并使用IOC / DI模式注入这些类。
答案 3 :(得分:0)
我认为你写的课程太多了。
我认为您对测试与外部API的交互不感兴趣,否则它将不再是纯粹的单元测试。
对于单元测试,您希望避免从API实例化类。最好的解决方案可能是使用模拟框架来模拟和进行深度白盒测试。我不熟悉.Net,但在Java方面,我们有很多模拟框架(例如mockito)。
为了能够使用模拟框架,您仍然需要调整一下代码,以便能够在运行时替换模拟的外部类。您将有一些注入外部类的点(如Preet所说:IOC / DI模式),例如:在构造函数级别,使用工厂方法和其他技术,允许您将实例化与正在运行的代码分离,并且您将指示模拟框架(或程序单元测试)在调用该函数时注入该模拟实例。
答案 4 :(得分:0)
如果可能,请考虑使用MOQ。您可以采用的其他方式是创建虚拟类(夹具),它将使用虚拟数据模拟外部组件。
Moq(发音为“Mock-you”或只是 “Mock”)是唯一的模拟库 for .NET从头开发到 充分利用.NET 3.5(即 Linq表达树)和C#3.0 功能(即lambda表达式) 使它最有效率, 类型安全和重构友好 模拟库可用。它 支持模拟接口以及 类。它的API非常简单 和直截了当,而不是 需要任何先验知识或 嘲笑概念的经验。