Mocking iPhone development

So now that I have ordinary-old unit testing is up and running, the next step is to get a mocking library in place so that I can simulate an external library’s behaviour under different scenarios.

OCMock seems to be the library of choice and the good news is that it appears to have a pretty neat API. The bad news comes when you want to, er, use it. I want to have the OCMock library only linked to my testing targets, which ought to be straight-forward enough, but following OCMock’s instructions rigorously only led me to pain. Here is a dead-simple test:

#import "LogicTests.h"
#import <OCMock/OCMock.h>

@implementation LogicTests

- (void)testAcceptsStubbedMethod {
    id mock = [OCMockObject mockForClass: [NSString class]];
    [[mock stub] lowercaseString];
    [mock lowercaseString];


And the error that I get when trying to build the LogicTests target:

linker error window

What’s going on here? XCode must recognise that the library is imported OK because it has OCMockObject correctly syntax highlighted, but the build fails at the linking stage. After much googling, Vincent Daubry appears to have the answer. It seems that there is some sort of incompatibility introduced between XCode 3.2.3, iOS4 and OCMock. Given that I am running XCode 3.2.5, iOS4 and OCMock 1.7, it felt likely that I had the same problem. Sure enough, replacing OCMock 1.7 with the latest version from its subversion repository did the trick. Annoyingly, 1.7 was released after Vincent’s post and I made the mistake of assuming that this more recent release would include the fix. Apparently not.

Having confirmed that having built OCMock from its source myself and using that rather than the released version 1.7 hadn’t broken any of the other project configurations led me to discover the next issue. Running the application on my device no longer works!

This appears to be because I made the application target depend upon the logic testing target, as suggested by Apple’s own documentation. This has the immense benefit that the tests are always run before running the application and ensures that the tests will be run regularly. I really can’t be bothered right now to work out how to resolve this1, so I will just have to make do with making my application target independent of my testing target, and make sure I remember to run my tests myself.

[1] My guess is that something along the lines of making the project's Library Search Paths use the $(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) variables to link to specific builds of OCMock ought to do the trick. I still don't want my application to include references to its testing dependencies though, which this approach doesn't solve.

comments powered by Disqus