如何对互联网协议实施进行单元测试?

Sve*_*ven 6 sockets cocoa unit-testing objective-c ocmock

我决定在我的项目中添加单元测试,并以测试驱动的方式继续开发.我目前正在为ManageSieve客户端对象实现单元测试,我不确定测试该野兽的最佳方法是什么.

我的SieveClient对象依赖于对网络通信的其他两个对象:CocoaAsyncSocket和我自己的SaslConn目标,这是我周围的赛勒斯SASL库来处理身份验证方法包装.为了测试,我需要用模拟对象替换它们.我将使用OCMock框架.我不太清楚如何做到这一点,因为SieveClient对象需要自己创建这些对象.现在我覆盖该对象的(私有)setter,以便始终使用OCMocks partialMockForObject:方法安装我的模拟对象.但这对我来说不合适.有什么想法可以更好地解决这个问题?

我遇到的另一个问题是套接字本身.为了能够测试协议细节,我需要一种从套接字返回预定义测试数据的方法.我想我可以使用OCMock机制伪造套接字的返回值.但是由于CocoaAsyncSocket提供了许多不同的方法来从套接字读取数据,我必须准确地知道协议对象使用哪种顺序.我不希望我的单元测试依赖于我的协议对象的实现细节.那我该怎么办?手动为套接字类实现模拟对象?这似乎并不重要,所以我可能也需要进行单元测试.这是一个好主意吗?

我读过,如果有些东西很难测试,它的设计可能也不是很好.但我不知道我怎么能做得更好,因为困难的部分在于我必须做的插座交互.

如果您想查看代码,可以在Bitbucket找到它:SieveClient.mSieveClient.h

编辑:依赖注入

所以我读到了依赖注入,我想我将使用它来将对象AsyncSocketSaslConn对象放入我的SieveClient对象中.我将更改我的构造函数以接受这些对象并使用它们.由于这个类的用户通常不关心套接字和SASL对象,我将添加一个工厂方法(以方便构造函数的形式),只创建这些对象并将它们传递给构造函数.

但这只解决了我测试问题的第一个(也更容易)部分.

egl*_*ius 7

但后来我拒绝了这个想法,因为它没有多大帮助.我可以更轻松地测试SieveClient对象,这是真的.但是我在测试新对象时会遇到同样的问题.在我看来,这只是为以后提出麻烦.特别是因为我什么都没有,我可以重新使用新课程.

这不是同一个问题.

我假设您需要SieveClient来内部控制其他对象的实例化,因为它是您不希望公开的API的一部分.如果这就是原因,通过分离它们,您将不再具有相同的需求,因为您可以让SieveClient控制绑定,而执行协议的其他部分接收它将使用的实例.

通过执行上述操作,您可以将模拟对象移交给协议实现.那些嘲笑会有你可能需要的任何期望.如果你发现它最终会让它过于参与,那么你可能需要重新调整职责,这通常会导致更简洁/更简单的协议实现(如果你发现需要进行这些单元测试).

如上所述,您还需要考虑您尝试测试的代码是否尽可能专注于协议,并且没有任何额外的元素.如果是这种情况,它就不适合进行单元测试,因为它的唯一责任是与外部系统的交互.我决定这个系统中的协议规范有多重要,如果它全部与外部系统集成,我会把它当作一个集中的集成测试,而不是真正的外部系统,并且与单元测试保持分离(所以它不会影响运行系统其余部分的单元测试所需的速度).


在由于编辑重新阅读问题之后,我必须强调我所说的关于上面的集中集成测试.你问:

但是由于CocoaAsyncSocket提供了许多不同的方法来从套接字读取数据,我必须确切地知道协议对象使用哪种顺序.我不希望我的单元测试依赖于我的协议对象的实现细节.那我该怎么办?手动为套接字类实现模拟对象?这似乎并不重要,所以我可能也需要进行单元测试.这是一个好主意吗?

如果您正在处理一个非常复杂的对象,并且该对象都是关于超出边界的集成,那么通常最好将其作为单元测试的一部分来避免.在那种情况下,您需要一个集中的集成测试/来打击真正的外部系统.这并不意味着代码的其余部分的所有单元测试,命中外部系统,只是使用该对象的非常简单的代码/类单元.

在你的场景中,很可能是这样的对象是SieveClient,在这种情况下忘记了那段代码的单元测试.您想要做的是在测试使用它的代码时模拟SieveClient.另一方面,如果您发现SieveClient远不止于此,您希望添加一个简化这些通信方面的类,这就是您在测试SieveClient时所模仿的内容,以及您针对的重点集成测试.

这种类型的测试是一种非常有效的方法,可以确保与外部交互的代码按预期工作,因为这是所涉及的类和测试的焦点.如果外部系统上的某些东西开始以不同的方式工作,你会清楚地注意到它 - 而不是将它与你的应用程序逻辑混合在一起,或者最糟糕的是根本没有测试


Don*_*ows 2

您能否将您正在做的事情分成两部分,一部分是抽象协议,另一部分是与套接字的绑定?然后,您可以更轻松地测试抽象协议,并将绑定测试的重点放在它是否正确调用任何连接的抽象协议的方法/操作。

抽象地讲,您将减少代码各部分之间的耦合。这提高了可测试性,但代价是整体复杂性有所增加(尽管还不错,因为您可以通过关注点分离获得更好的工具来管理它),并且可能会降低性能(尽管对大多数系统来说这并不是什么大问题;你的计算机比它的 I/O 子系统快得多)。