Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 如何对internet协议实现进行单元测试?_Objective C_Cocoa_Unit Testing_Sockets_Ocmock - Fatal编程技术网

Objective c 如何对internet协议实现进行单元测试?

Objective c 如何对internet协议实现进行单元测试?,objective-c,cocoa,unit-testing,sockets,ocmock,Objective C,Cocoa,Unit Testing,Sockets,Ocmock,我决定将单元测试添加到我的项目中,并以测试驱动的方式继续开发。我目前正在为我的ManageSeeve客户端对象实施单元测试,我不确定测试该beast的最佳方法是什么 我的SieveClient对象依赖于两个其他对象进行网络通信:cocoaaasyncsocket和我自己的SaslConn对象,它是我对Cyrus SASL库的包装,用于处理身份验证方法。为了进行测试,我需要用模拟对象替换这些对象。我将使用OCMock框架来实现这一点。我不太清楚该怎么做,因为SieveClient对象需要自己创建这

我决定将单元测试添加到我的项目中,并以测试驱动的方式继续开发。我目前正在为我的ManageSeeve客户端对象实施单元测试,我不确定测试该beast的最佳方法是什么

我的
SieveClient
对象依赖于两个其他对象进行网络通信:
cocoaaasyncsocket
和我自己的
SaslConn
对象,它是我对Cyrus SASL库的包装,用于处理身份验证方法。为了进行测试,我需要用模拟对象替换这些对象。我将使用OCMock框架来实现这一点。我不太清楚该怎么做,因为SieveClient对象需要自己创建这些对象。现在,我覆盖该对象的(私有)setter,以便始终使用OCMocks
partialMockForObject:
方法安装我的模拟对象。但我觉得这不对。有没有办法更好地解决这个问题

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

我读到过,如果某个东西很难测试,那么它可能也不是设计得很好。但我不知道如何才能做得更好,因为最困难的部分在于与套接字的交互,我必须这样做

如果您想查看代码,可以在Bitbucket:和

编辑:依赖项注入 因此,我阅读了有关依赖注入的内容,我想我将使用它将
AsyncSocket
SaslConn
对象放入我的
siveclient
对象中。我将更改构造函数以接受这些对象并使用它们。因为这个类的用户通常不关心套接字和SASL对象,所以我将添加一个工厂方法(以方便构造函数的形式),它只创建这些对象并将它们传递给构造函数


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

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

抽象地说,您将减少代码各部分之间的耦合。这增加了可测试性,但代价是总体复杂度有所增加(虽然不是很糟糕,因为您通过分离关注点获得了更好的工具来管理它),性能也有一些潜在的下降(但大多数系统都没有太大问题;您的计算机比其I/O子系统快得多)

但后来我拒绝了这个想法,因为它 不会有多大帮助。我可以测试一下 SieveClient对象更容易, 对。但我也会有同样的 测试新对象时出现的问题。 在我看来,这只是 把这件事留到以后再说。尤其地 因为我没有什么可以重复使用的 这是一个新的班级

这不是同样的问题

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

通过执行上述操作,您可以将模拟对象移交给协议实现这些模拟将有您可能需要的任何期望。如果您发现它最终会导致它过于复杂,那么您可能需要重新关注职责,这通常会导致更干净/更简单的协议实现(如果您发现您需要通过执行这些单元测试来实现)

如上所述,您还需要考虑您尝试测试的代码是否尽可能集中在协议上,并且没有任何额外的元素。如果是这样的话,它就不是进行单元测试的好选择,因为它的唯一责任是与外部系统的交互。我会决定协议规范在这个系统中有多重要,如果它完全是关于与外部系统的集成,我会将它视为一个集中的集成测试,而不是命中真正的外部系统,并与单元测试保持分离(因此它不会影响系统其余部分运行单元测试所需的速度)


由于编辑的原因,在重新阅读了问题之后,我必须强调一下我所说的关于上述重点集成测试的内容。你问:

但是由于CocoaAsyncSocket提供 有许多不同的读取数据的方法 从插座上我必须准确地知道 协议正在使用的 对象的顺序。我不想要我的孩子 单元测试取决于 我的协议的实现细节 对象那我在这里该怎么办? 为套接字实现一个模拟对象 手工上课?这似乎不是小事, 因此,我可能需要对其进行单元测试 那也是。这是个好主意吗

如果您正在处理一个非常复杂的对象,并且该对象都是关于边界之外的集成的,那么您通常最好在单元测试中避免使用它。在那个场景里