在Objective-C中模拟C库函数

在Objective-C中模拟C库函数,objective-c,unit-testing,ocmock,Objective C,Unit Testing,Ocmock,我是Objective-C的初学者,但我使用过jUnit 为了对代码进行单元测试,我需要能够模拟网络,我正在通过CFStreamCreatePairWithSocketToHost函数使用网络 根据对的回答,这在OCMock中是不可能的。是否有任何框架或技术允许这样做 我不想仅仅为了使代码更易于测试而使用一些过于复杂的Java风格的IoC框架,但我必须指出,Spring的好处之一是,当您通过接口使用所有东西并通过依赖项注入配置实现时,很少会出现这样的问题。这就是前进的方向,还是有更简单的解决方案

我是Objective-C的初学者,但我使用过jUnit

为了对代码进行单元测试,我需要能够模拟网络,我正在通过
CFStreamCreatePairWithSocketToHost
函数使用网络

根据对的回答,这在OCMock中是不可能的。是否有任何框架或技术允许这样做


我不想仅仅为了使代码更易于测试而使用一些过于复杂的Java风格的IoC框架,但我必须指出,Spring的好处之一是,当您通过接口使用所有东西并通过依赖项注入配置实现时,很少会出现这样的问题。这就是前进的方向,还是有更简单的解决方案?

我不知道有什么方法可以模拟C函数。如果可以,它必须是您正在使用的C编译器中的一个特性

据我所知,叮当没有任何这样的功能,所以你不能这样做

CFStreamCreatePairWithSocketToHost()
函数位于内存中的固定位置,不能移动,也不能在内存位置放置任何其他内容-它是设备上运行的每个应用程序共享的系统函数,更改它将断开当前正在执行的其他每个应用程序

不能用C函数做这样的事情是C执行速度比大多数其他编程语言更快的原因。如果希望能够模拟函数,那么不要用C语言编写代码。改为使用objective-c,使用方法
createPairWithSocketToHost
创建一个类
MyCFStream
,用一行代码调用c函数,在你的应用程序中随处可见。您可以轻松地在类中模拟该方法


但是,您的包装函数将比直接使用内置C函数慢得多。

另一个选项是创建一个宏,重命名C函数,并在调试中调用包装函数,在prod中调用系统C函数。这将允许您模拟/swizzle Objective-C函数进行单元测试,但要保持产品的速度

这种方法有一个严重的问题,即它会在debug/prod之间更改您的实现,但这是一种选择。在这种情况下,我强烈建议进行一些集成测试,并在prod环境中运行它们,以在相当高的程度上确定代码是否按预期运行

无论如何,如果您对此感兴趣,请了解/了解您正在做什么,因为如果操作不当,这可能是一种相当危险的方法。

您可以在内存中重新绑定系统(所有)函数指针以进行测试。有多种技术可以做到这一点(例如DYLD_INSERT_库),但最简单的方法是使用Facebook上的便利库:


不,在C方法上没有内省(模拟所需)。时期如果你能做到这一点,那将是非常不可靠和未定义的行为。也许在桌面应用程序上,你可以交叉链接(比如valgrind和strace/dtrace),但在iPhone上你就是做不到。使用Obj-C方法,直到在运行时实际调用该方法时,才选择实际的实现。对于静态链接的C库(这里的细节我可能错了),函数的实现以及在代码中调用函数的位置在编译时绑定。所以这真的不可能
#import "fishhook.h"

static void *(*orig_malloc)(size_t __size);
void *my_malloc(size_t size)
{
    printf("Allocated: %zu\n", size);
    return orig_malloc(size);
}
 /* .. */
- (void)testMyTestCase
{
    //hook malloc
    rebind_symbols((struct rebinding[1]){{"malloc", my_malloc, (void *)&orig_malloc}}, 1);

    char *a = malloc(100);

    //restore original
    rebind_symbols((struct rebinding[1]){{"malloc", orig_malloc, NULL}}, 1);

    //...
}