I'm a beginner to Objective-C, but I've used jUnit a fair bit.
For unit testing my code, I need to be able to mock the network, which I'm using through the CFStreamCreatePairWithSocketToHost
function.
Per the answer to How to mock a C-function using OCMock, this is impossible in OCMock. Are there any frameworks or techniques that allow this?
I'd rather not commit to using some overcomplicated Java-esque IoC framework just to make my code easier to test, but I must say that one of the benefits of Spring is that issues like this rarely come up when you use everything through an interface and configure the implementations through dependency injection. Is that the way forward here, or is there a simpler solution?
You can rebind system(all) function pointers in memory for testing. There are multiple techniques to do it(e.g. DYLD_INSERT_LIBRARIES), but the easiest way is to use convenience library from Facebook: https://github.com/facebook/fishhook
#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);
//...
}
I don't know of any way to mock a C function. If it can be done, it would have to be a feature in the C compiler you're using.
As far as I know, Clang does not have any such feature, so you can't do it.
The CFStreamCreatePairWithSocketToHost()
function is at a fixed location in memory and it cannot be moved nor can anything else be placed at the memory location - it's a system function shared by every app running on the device, changing it would break every other app that is currently executing.
The inability to do things like this with C function is the reason why C executes faster than most other programming languages. If you want to be able to mock functions, then do not write your code in the C language. Use objective-c instead, make a class MyCFStream
with a method createPairWithSocketToHost
, with a single line of code calling the C function use that everywhere in your app. You can easily mock the method in the class.
Your wrapper function will, however, be much slower than using the built in C function directly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With